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 {...@@ -95,7 +95,7 @@ const Tokenizer = struct {
95 };95 };
9696
97 fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer {97 fn init(source_file_name: []const u8, buffer: []const u8) Tokenizer {
98 return Tokenizer {98 return Tokenizer{
99 .buffer = buffer,99 .buffer = buffer,
100 .index = 0,100 .index = 0,
101 .state = State.Start,101 .state = State.Start,
...@@ -105,7 +105,7 @@ const Tokenizer = struct {...@@ -105,7 +105,7 @@ const Tokenizer = struct {
105 }105 }
106106
107 fn next(self: &Tokenizer) Token {107 fn next(self: &Tokenizer) Token {
108 var result = Token {108 var result = Token{
109 .id = Token.Id.Eof,109 .id = Token.Id.Eof,
110 .start = self.index,110 .start = self.index,
111 .end = undefined,111 .end = undefined,
...@@ -197,7 +197,7 @@ const Tokenizer = struct {...@@ -197,7 +197,7 @@ const Tokenizer = struct {
197 };197 };
198198
199 fn getTokenLocation(self: &Tokenizer, token: &const Token) Location {199 fn getTokenLocation(self: &Tokenizer, token: &const Token) Location {
200 var loc = Location {200 var loc = Location{
201 .line = 0,201 .line = 0,
202 .column = 0,202 .column = 0,
203 .line_start = 0,203 .line_start = 0,
...@@ -346,7 +346,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -346,7 +346,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
346 break;346 break;
347 },347 },
348 Token.Id.Content => {348 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] });
350 },350 },
351 Token.Id.BracketOpen => {351 Token.Id.BracketOpen => {
352 const tag_token = try eatToken(tokenizer, Token.Id.TagContent);352 const tag_token = try eatToken(tokenizer, Token.Id.TagContent);
...@@ -365,11 +365,13 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -365,11 +365,13 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
365 header_stack_size += 1;365 header_stack_size += 1;
366366
367 const urlized = try urlize(allocator, content);367 const urlized = try urlize(allocator, content);
368 try nodes.append(Node{.HeaderOpen = HeaderOpen {368 try nodes.append(Node{
369 .name = content,369 .HeaderOpen = HeaderOpen{
370 .url = urlized,370 .name = content,
371 .n = header_stack_size,371 .url = urlized,
372 }});372 .n = header_stack_size,
373 },
374 });
373 if (try urls.put(urlized, tag_token)) |other_tag_token| {375 if (try urls.put(urlized, tag_token)) |other_tag_token| {
374 parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {};376 parseError(tokenizer, tag_token, "duplicate header url: #{}", urlized) catch {};
375 parseError(tokenizer, other_tag_token, "other tag here") catch {};377 parseError(tokenizer, other_tag_token, "other tag here") catch {};
...@@ -407,14 +409,14 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -407,14 +409,14 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
407 switch (see_also_tok.id) {409 switch (see_also_tok.id) {
408 Token.Id.TagContent => {410 Token.Id.TagContent => {
409 const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end];411 const content = tokenizer.buffer[see_also_tok.start..see_also_tok.end];
410 try list.append(SeeAlsoItem {412 try list.append(SeeAlsoItem{
411 .name = content,413 .name = content,
412 .token = see_also_tok,414 .token = see_also_tok,
413 });415 });
414 },416 },
415 Token.Id.Separator => {},417 Token.Id.Separator => {},
416 Token.Id.BracketClose => {418 Token.Id.BracketClose => {
417 try nodes.append(Node {.SeeAlso = list.toOwnedSlice() } );419 try nodes.append(Node{ .SeeAlso = list.toOwnedSlice() });
418 break;420 break;
419 },421 },
420 else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),422 else => return parseError(tokenizer, see_also_tok, "invalid see_also token"),
...@@ -438,8 +440,8 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -438,8 +440,8 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
438 }440 }
439 };441 };
440442
441 try nodes.append(Node {443 try nodes.append(Node{
442 .Link = Link {444 .Link = Link{
443 .url = try urlize(allocator, url_name),445 .url = try urlize(allocator, url_name),
444 .name = name,446 .name = name,
445 .token = name_tok,447 .token = name_tok,
...@@ -463,24 +465,24 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -463,24 +465,24 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
463 var code_kind_id: Code.Id = undefined;465 var code_kind_id: Code.Id = undefined;
464 var is_inline = false;466 var is_inline = false;
465 if (mem.eql(u8, code_kind_str, "exe")) {467 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 };
467 } else if (mem.eql(u8, code_kind_str, "exe_err")) {469 } 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 };
469 } else if (mem.eql(u8, code_kind_str, "test")) {471 } else if (mem.eql(u8, code_kind_str, "test")) {
470 code_kind_id = Code.Id.Test;472 code_kind_id = Code.Id.Test;
471 } else if (mem.eql(u8, code_kind_str, "test_err")) {473 } 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 };
473 name = "test";475 name = "test";
474 } else if (mem.eql(u8, code_kind_str, "test_safety")) {476 } 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 };
476 name = "test";478 name = "test";
477 } else if (mem.eql(u8, code_kind_str, "obj")) {479 } 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 };
479 } else if (mem.eql(u8, code_kind_str, "obj_err")) {481 } 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 };
481 name = "test";483 name = "test";
482 } else if (mem.eql(u8, code_kind_str, "syntax")) {484 } 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 };
484 is_inline = true;486 is_inline = true;
485 } else {487 } else {
486 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);488 return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {}", code_kind_str);
...@@ -514,17 +516,20 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -514,17 +516,20 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
514 return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name);516 return parseError(tokenizer, end_code_tag, "invalid token inside code_begin: {}", end_tag_name);
515 }517 }
516 _ = try eatToken(tokenizer, Token.Id.BracketClose);518 _ = try eatToken(tokenizer, Token.Id.BracketClose);
517 } else unreachable; // TODO issue #707519 } else
518 try nodes.append(Node {.Code = Code {520 unreachable; // TODO issue #707
519 .id = code_kind_id,521 try nodes.append(Node{
520 .name = name,522 .Code = Code{
521 .source_token = source_token,523 .id = code_kind_id,
522 .is_inline = is_inline,524 .name = name,
523 .mode = mode,525 .source_token = source_token,
524 .link_objects = link_objects.toOwnedSlice(),526 .is_inline = is_inline,
525 .target_windows = target_windows,527 .mode = mode,
526 .link_libc = link_libc,528 .link_objects = link_objects.toOwnedSlice(),
527 }});529 .target_windows = target_windows,
530 .link_libc = link_libc,
531 },
532 });
528 tokenizer.code_node_count += 1;533 tokenizer.code_node_count += 1;
529 } else {534 } else {
530 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);535 return parseError(tokenizer, tag_token, "unrecognized tag name: {}", tag_name);
...@@ -534,7 +539,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {...@@ -534,7 +539,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) !Toc {
534 }539 }
535 }540 }
536541
537 return Toc {542 return Toc{
538 .nodes = nodes.toOwnedSlice(),543 .nodes = nodes.toOwnedSlice(),
539 .toc = toc_buf.toOwnedSlice(),544 .toc = toc_buf.toOwnedSlice(),
540 .urls = urls,545 .urls = urls,
...@@ -727,16 +732,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -727,16 +732,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
727 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);732 const name_plus_ext = try std.fmt.allocPrint(allocator, "{}.zig", code.name);
728 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);733 const tmp_source_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_ext);
729 try io.writeFile(allocator, tmp_source_file_name, trimmed_raw_source);734 try io.writeFile(allocator, tmp_source_file_name, trimmed_raw_source);
730 735
731 switch (code.id) {736 switch (code.id) {
732 Code.Id.Exe => |expected_outcome| {737 Code.Id.Exe => |expected_outcome| {
733 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);738 const name_plus_bin_ext = try std.fmt.allocPrint(allocator, "{}{}", code.name, exe_ext);
734 const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);739 const tmp_bin_file_name = try os.path.join(allocator, tmp_dir_name, name_plus_bin_ext);
735 var build_args = std.ArrayList([]const u8).init(allocator);740 var build_args = std.ArrayList([]const u8).init(allocator);
736 defer build_args.deinit();741 defer build_args.deinit();
737 try build_args.appendSlice([][]const u8 {zig_exe,742 try build_args.appendSlice([][]const u8{
738 "build-exe", tmp_source_file_name,743 zig_exe,
739 "--output", tmp_bin_file_name,744 "build-exe",
745 tmp_source_file_name,
746 "--output",
747 tmp_bin_file_name,
740 });748 });
741 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);749 try out.print("<pre><code class=\"shell\">$ zig build-exe {}.zig", code.name);
742 switch (code.mode) {750 switch (code.mode) {
...@@ -766,10 +774,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -766,10 +774,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
766 try build_args.append("c");774 try build_args.append("c");
767 try out.print(" --library c");775 try out.print(" --library c");
768 }776 }
769 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(777 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
770 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
774 const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {781 const result = if (expected_outcome == ExpectedOutcome.Fail) blk: {
775 const result = try os.ChildProcess.exec(allocator, run_args, null, null, max_doc_file_size);782 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...@@ -777,7 +784,10 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
777 os.ChildProcess.Term.Exited => |exit_code| {784 os.ChildProcess.Term.Exited => |exit_code| {
778 if (exit_code == 0) {785 if (exit_code == 0) {
779 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);786 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");
781 return parseError(tokenizer, code.source_token, "example incorrectly compiled");791 return parseError(tokenizer, code.source_token, "example incorrectly compiled");
782 }792 }
783 },793 },
...@@ -785,11 +795,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -785,11 +795,9 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
785 }795 }
786 break :blk result;796 break :blk result;
787 } else blk: {797 } else blk: {
788 break :blk exec(allocator, run_args) catch return parseError(798 break :blk exec(allocator, run_args) catch return parseError(tokenizer, code.source_token, "example crashed");
789 tokenizer, code.source_token, "example crashed");
790 };799 };
791800
792
793 const escaped_stderr = try escapeHtml(allocator, result.stderr);801 const escaped_stderr = try escapeHtml(allocator, result.stderr);
794 const escaped_stdout = try escapeHtml(allocator, result.stdout);802 const escaped_stdout = try escapeHtml(allocator, result.stdout);
795803
...@@ -802,7 +810,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -802,7 +810,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
802 var test_args = std.ArrayList([]const u8).init(allocator);810 var test_args = std.ArrayList([]const u8).init(allocator);
803 defer test_args.deinit();811 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 });
806 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);818 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
807 switch (code.mode) {819 switch (code.mode) {
808 builtin.Mode.Debug => {},820 builtin.Mode.Debug => {},
...@@ -821,13 +833,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -821,13 +833,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
821 }833 }
822 if (code.target_windows) {834 if (code.target_windows) {
823 try test_args.appendSlice([][]const u8{835 try test_args.appendSlice([][]const u8{
824 "--target-os", "windows",836 "--target-os",
825 "--target-arch", "x86_64",837 "windows",
826 "--target-environ", "msvc",838 "--target-arch",
839 "x86_64",
840 "--target-environ",
841 "msvc",
827 });842 });
828 }843 }
829 const result = exec(allocator, test_args.toSliceConst()) catch return parseError(844 const result = exec(allocator, test_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "test failed");
830 tokenizer, code.source_token, "test failed");
831 const escaped_stderr = try escapeHtml(allocator, result.stderr);845 const escaped_stderr = try escapeHtml(allocator, result.stderr);
832 const escaped_stdout = try escapeHtml(allocator, result.stdout);846 const escaped_stdout = try escapeHtml(allocator, result.stdout);
833 try out.print("\n{}{}</code></pre>\n", escaped_stderr, escaped_stdout);847 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...@@ -836,7 +850,13 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
836 var test_args = std.ArrayList([]const u8).init(allocator);850 var test_args = std.ArrayList([]const u8).init(allocator);
837 defer test_args.deinit();851 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 });
840 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);860 try out.print("<pre><code class=\"shell\">$ zig test {}.zig", code.name);
841 switch (code.mode) {861 switch (code.mode) {
842 builtin.Mode.Debug => {},862 builtin.Mode.Debug => {},
...@@ -858,13 +878,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -858,13 +878,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
858 os.ChildProcess.Term.Exited => |exit_code| {878 os.ChildProcess.Term.Exited => |exit_code| {
859 if (exit_code == 0) {879 if (exit_code == 0) {
860 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);880 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");
862 return parseError(tokenizer, code.source_token, "example incorrectly compiled");885 return parseError(tokenizer, code.source_token, "example incorrectly compiled");
863 }886 }
864 },887 },
865 else => {888 else => {
866 warn("{}\nThe following command crashed:\n", result.stderr);889 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");
868 return parseError(tokenizer, code.source_token, "example compile crashed");894 return parseError(tokenizer, code.source_token, "example compile crashed");
869 },895 },
870 }896 }
...@@ -881,7 +907,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -881,7 +907,11 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
881 var test_args = std.ArrayList([]const u8).init(allocator);907 var test_args = std.ArrayList([]const u8).init(allocator);
882 defer test_args.deinit();908 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 });
885 switch (code.mode) {915 switch (code.mode) {
886 builtin.Mode.Debug => {},916 builtin.Mode.Debug => {},
887 builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"),917 builtin.Mode.ReleaseSafe => try test_args.append("--release-safe"),
...@@ -894,13 +924,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -894,13 +924,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
894 os.ChildProcess.Term.Exited => |exit_code| {924 os.ChildProcess.Term.Exited => |exit_code| {
895 if (exit_code == 0) {925 if (exit_code == 0) {
896 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);926 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");
898 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");931 return parseError(tokenizer, code.source_token, "example test incorrectly succeeded");
899 }932 }
900 },933 },
901 else => {934 else => {
902 warn("{}\nThe following command crashed:\n", result.stderr);935 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");
904 return parseError(tokenizer, code.source_token, "example compile crashed");940 return parseError(tokenizer, code.source_token, "example compile crashed");
905 },941 },
906 }942 }
...@@ -918,9 +954,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -918,9 +954,15 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
918 var build_args = std.ArrayList([]const u8).init(allocator);954 var build_args = std.ArrayList([]const u8).init(allocator);
919 defer build_args.deinit();955 defer build_args.deinit();
920956
921 try build_args.appendSlice([][]const u8 {zig_exe, "build-obj", tmp_source_file_name,957 try build_args.appendSlice([][]const u8{
922 "--color", "on",958 zig_exe,
923 "--output", tmp_obj_file_name});959 "build-obj",
960 tmp_source_file_name,
961 "--color",
962 "on",
963 "--output",
964 tmp_obj_file_name,
965 });
924966
925 if (!code.is_inline) {967 if (!code.is_inline) {
926 try out.print("<pre><code class=\"shell\">$ zig build-obj {}.zig", code.name);968 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...@@ -954,13 +996,19 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
954 os.ChildProcess.Term.Exited => |exit_code| {996 os.ChildProcess.Term.Exited => |exit_code| {
955 if (exit_code == 0) {997 if (exit_code == 0) {
956 warn("{}\nThe following command incorrectly succeeded:\n", result.stderr);998 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");
958 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded");1003 return parseError(tokenizer, code.source_token, "example build incorrectly succeeded");
959 }1004 }
960 },1005 },
961 else => {1006 else => {
962 warn("{}\nThe following command crashed:\n", result.stderr);1007 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");
964 return parseError(tokenizer, code.source_token, "example compile crashed");1012 return parseError(tokenizer, code.source_token, "example compile crashed");
965 },1013 },
966 }1014 }
...@@ -975,8 +1023,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -975,8 +1023,7 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
975 try out.print("</code></pre>\n");1023 try out.print("</code></pre>\n");
976 }1024 }
977 } else {1025 } else {
978 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(1026 _ = exec(allocator, build_args.toSliceConst()) catch return parseError(tokenizer, code.source_token, "example failed to compile");
979 tokenizer, code.source_token, "example failed to compile");
980 }1027 }
981 if (!code.is_inline) {1028 if (!code.is_inline) {
982 try out.print("</code></pre>\n");1029 try out.print("</code></pre>\n");
...@@ -987,7 +1034,6 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var...@@ -987,7 +1034,6 @@ fn genHtml(allocator: &mem.Allocator, tokenizer: &Tokenizer, toc: &Toc, out: var
987 },1034 },
988 }1035 }
989 }1036 }
990
991}1037}
9921038
993fn exec(allocator: &mem.Allocator, args: []const []const u8) !os.ChildProcess.ExecResult {1039fn 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...@@ -996,13 +1042,19 @@ fn exec(allocator: &mem.Allocator, args: []const []const u8) !os.ChildProcess.Ex
996 os.ChildProcess.Term.Exited => |exit_code| {1042 os.ChildProcess.Term.Exited => |exit_code| {
997 if (exit_code != 0) {1043 if (exit_code != 0) {
998 warn("{}\nThe following command exited with code {}:\n", result.stderr, exit_code);1044 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");
1000 return error.ChildExitError;1049 return error.ChildExitError;
1001 }1050 }
1002 },1051 },
1003 else => {1052 else => {
1004 warn("{}\nThe following command crashed:\n", result.stderr);1053 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");
1006 return error.ChildCrashed;1058 return error.ChildCrashed;
1007 },1059 },
1008 }1060 }
example/guess_number/main.zig+1-1
...@@ -23,7 +23,7 @@ pub fn main() !void {...@@ -23,7 +23,7 @@ pub fn main() !void {
2323
24 while (true) {24 while (true) {
25 try stdout.print("\nGuess a number between 1 and 100: ");25 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
28 const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {28 const line_len = io.readLine(line_buf[0..]) catch |err| switch (err) {
29 error.InputTooLong => {29 error.InputTooLong => {
example/hello_world/hello_libc.zig+1-2
...@@ -8,8 +8,7 @@ const c = @cImport({...@@ -8,8 +8,7 @@ const c = @cImport({
8const msg = c"Hello, world!\n";8const msg = c"Hello, world!\n";
99
10export fn main(argc: c_int, argv: &&u8) c_int {10export fn main(argc: c_int, argv: &&u8) c_int {
11 if (c.printf(msg) != c_int(c.strlen(msg)))11 if (c.printf(msg) != c_int(c.strlen(msg))) return -1;
12 return -1;
1312
14 return 0;13 return 0;
15}14}
example/mix_o_files/build.zig+1-3
...@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {...@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {
4 const obj = b.addObject("base64", "base64.zig");4 const obj = b.addObject("base64", "base64.zig");
55
6 const exe = b.addCExecutable("test");6 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8 {7 exe.addCompileFlags([][]const u8{"-std=c99"});
8 "-std=c99",
9 });
10 exe.addSourceFile("test.c");8 exe.addSourceFile("test.c");
11 exe.addObject(obj);9 exe.addObject(obj);
1210
example/shared_library/build.zig+1-3
...@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {...@@ -4,9 +4,7 @@ pub fn build(b: &Builder) void {
4 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));4 const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
55
6 const exe = b.addCExecutable("test");6 const exe = b.addCExecutable("test");
7 exe.addCompileFlags([][]const u8 {7 exe.addCompileFlags([][]const u8{"-std=c99"});
8 "-std=c99",
9 });
10 exe.addSourceFile("test.c");8 exe.addSourceFile("test.c");
11 exe.linkLibrary(lib);9 exe.linkLibrary(lib);
1210
src-self-hosted/introspect.zig+1-3
...@@ -48,9 +48,7 @@ pub fn resolveZigLibDir(allocator: &mem.Allocator) ![]u8 {...@@ -48,9 +48,7 @@ pub fn resolveZigLibDir(allocator: &mem.Allocator) ![]u8 {
48 \\Unable to find zig lib directory: {}.48 \\Unable to find zig lib directory: {}.
49 \\Reinstall Zig or use --zig-install-prefix.49 \\Reinstall Zig or use --zig-install-prefix.
50 \\50 \\
51 ,51 , @errorName(err));
52 @errorName(err)
53 );
5452
55 return error.ZigLibDirNotFound;53 return error.ZigLibDirNotFound;
56 };54 };
src-self-hosted/ir.zig-1
...@@ -108,5 +108,4 @@ pub const Instruction = struct {...@@ -108,5 +108,4 @@ pub const Instruction = struct {
108 ArgType,108 ArgType,
109 Export,109 Export,
110 };110 };
111
112};111};
src-self-hosted/main.zig+102-67
...@@ -37,7 +37,7 @@ const usage =...@@ -37,7 +37,7 @@ const usage =
37 \\ zen Print zen of zig and exit37 \\ zen Print zen of zig and exit
38 \\38 \\
39 \\39 \\
40 ;40;
4141
42const Command = struct {42const Command = struct {
43 name: []const u8,43 name: []const u8,
...@@ -63,22 +63,61 @@ pub fn main() !void {...@@ -63,22 +63,61 @@ pub fn main() !void {
63 os.exit(1);63 os.exit(1);
64 }64 }
6565
66 const commands = []Command {66 const commands = []Command{
67 Command { .name = "build", .exec = cmdBuild },67 Command{
68 Command { .name = "build-exe", .exec = cmdBuildExe },68 .name = "build",
69 Command { .name = "build-lib", .exec = cmdBuildLib },69 .exec = cmdBuild,
70 Command { .name = "build-obj", .exec = cmdBuildObj },70 },
71 Command { .name = "fmt", .exec = cmdFmt },71 Command{
72 Command { .name = "run", .exec = cmdRun },72 .name = "build-exe",
73 Command { .name = "targets", .exec = cmdTargets },73 .exec = cmdBuildExe,
74 Command { .name = "test", .exec = cmdTest },74 },
75 Command { .name = "translate-c", .exec = cmdTranslateC },75 Command{
76 Command { .name = "version", .exec = cmdVersion },76 .name = "build-lib",
77 Command { .name = "zen", .exec = cmdZen },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
79 // undocumented commands112 // undocumented commands
80 Command { .name = "help", .exec = cmdHelp },113 Command{
81 Command { .name = "internal", .exec = cmdInternal },114 .name = "help",
115 .exec = cmdHelp,
116 },
117 Command{
118 .name = "internal",
119 .exec = cmdInternal,
120 },
82 };121 };
83122
84 for (commands) |command| {123 for (commands) |command| {
...@@ -120,9 +159,9 @@ const usage_build =...@@ -120,9 +159,9 @@ const usage_build =
120 \\ --verbose-cimport Enable compiler debug output for C imports159 \\ --verbose-cimport Enable compiler debug output for C imports
121 \\160 \\
122 \\161 \\
123 ;162;
124163
125const args_build_spec = []Flag {164const args_build_spec = []Flag{
126 Flag.Bool("--help"),165 Flag.Bool("--help"),
127 Flag.Bool("--init"),166 Flag.Bool("--init"),
128 Flag.Arg1("--build-file"),167 Flag.Arg1("--build-file"),
...@@ -148,7 +187,7 @@ const missing_build_file =...@@ -148,7 +187,7 @@ const missing_build_file =
148 \\187 \\
149 \\See: `zig build --help` or `zig help` for more options.188 \\See: `zig build --help` or `zig help` for more options.
150 \\189 \\
151 ;190;
152191
153fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {192fn cmdBuild(allocator: &Allocator, args: []const []const u8) !void {
154 var flags = try Args.parse(allocator, args_build_spec, args);193 var flags = try Args.parse(allocator, args_build_spec, args);
...@@ -317,15 +356,23 @@ const usage_build_generic =...@@ -317,15 +356,23 @@ const usage_build_generic =
317 \\ --ver-patch [ver] Dynamic library semver patch version356 \\ --ver-patch [ver] Dynamic library semver patch version
318 \\357 \\
319 \\358 \\
320 ;359;
321360
322const args_build_generic = []Flag {361const args_build_generic = []Flag{
323 Flag.Bool("--help"),362 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
326 Flag.ArgMergeN("--assembly", 1),369 Flag.ArgMergeN("--assembly", 1),
327 Flag.Arg1("--cache-dir"),370 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 }),
329 Flag.Bool("--enable-timing-info"),376 Flag.Bool("--enable-timing-info"),
330 Flag.Arg1("--libc-include-dir"),377 Flag.Arg1("--libc-include-dir"),
331 Flag.Arg1("--name"),378 Flag.Arg1("--name"),
...@@ -471,7 +518,7 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo...@@ -471,7 +518,7 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo
471 os.exit(1);518 os.exit(1);
472 };519 };
473520
474 const asm_a= flags.many("assembly");521 const asm_a = flags.many("assembly");
475 const obj_a = flags.many("object");522 const obj_a = flags.many("object");
476 if (in_file == null and (obj_a == null or (??obj_a).len == 0) and (asm_a == null or (??asm_a).len == 0)) {523 if (in_file == null and (obj_a == null or (??obj_a).len == 0) and (asm_a == null or (??asm_a).len == 0)) {
477 try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");524 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...@@ -493,17 +540,16 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo
493 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);540 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);
494 defer allocator.free(zig_lib_dir);541 defer allocator.free(zig_lib_dir);
495542
496 var module =543 var module = try Module.create(
497 try Module.create(544 allocator,
498 allocator,545 root_name,
499 root_name,546 zig_root_source_file,
500 zig_root_source_file,547 Target.Native,
501 Target.Native,548 out_type,
502 out_type,549 build_mode,
503 build_mode,550 zig_lib_dir,
504 zig_lib_dir,551 full_cache_dir,
505 full_cache_dir552 );
506 );
507 defer module.destroy();553 defer module.destroy();
508554
509 module.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") ?? "0", 10);555 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...@@ -588,10 +634,10 @@ fn buildOutputType(allocator: &Allocator, args: []const []const u8, out_type: Mo
588 }634 }
589635
590 if (flags.single("mmacosx-version-min")) |ver| {636 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 };
592 }638 }
593 if (flags.single("mios-version-min")) |ver| {639 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 };
595 }641 }
596642
597 module.emit_file_type = emit_type;643 module.emit_file_type = emit_type;
...@@ -639,11 +685,9 @@ const usage_fmt =...@@ -639,11 +685,9 @@ const usage_fmt =
639 \\ --help Print this help and exit685 \\ --help Print this help and exit
640 \\686 \\
641 \\687 \\
642 ;688;
643689
644const args_fmt_spec = []Flag {690const args_fmt_spec = []Flag{Flag.Bool("--help")};
645 Flag.Bool("--help"),
646};
647691
648fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {692fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {
649 var flags = try Args.parse(allocator, args_fmt_spec, args);693 var flags = try Args.parse(allocator, args_fmt_spec, args);
...@@ -675,7 +719,6 @@ fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {...@@ -675,7 +719,6 @@ fn cmdFmt(allocator: &Allocator, args: []const []const u8) !void {
675 };719 };
676 defer tree.deinit();720 defer tree.deinit();
677721
678
679 var error_it = tree.errors.iterator(0);722 var error_it = tree.errors.iterator(0);
680 while (error_it.next()) |parse_error| {723 while (error_it.next()) |parse_error| {
681 const token = tree.tokens.at(parse_error.loc());724 const token = tree.tokens.at(parse_error.loc());
...@@ -721,8 +764,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {...@@ -721,8 +764,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
721 inline while (i < @memberCount(builtin.Arch)) : (i += 1) {764 inline while (i < @memberCount(builtin.Arch)) : (i += 1) {
722 comptime const arch_tag = @memberName(builtin.Arch, i);765 comptime const arch_tag = @memberName(builtin.Arch, i);
723 // NOTE: Cannot use empty string, see #918.766 // NOTE: Cannot use empty string, see #918.
724 comptime const native_str =767 comptime const native_str = if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
725 if (comptime mem.eql(u8, arch_tag, @tagName(builtin.arch))) " (native)\n" else "\n";
726768
727 try stdout.print(" {}{}", arch_tag, native_str);769 try stdout.print(" {}{}", arch_tag, native_str);
728 }770 }
...@@ -735,8 +777,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {...@@ -735,8 +777,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
735 inline while (i < @memberCount(builtin.Os)) : (i += 1) {777 inline while (i < @memberCount(builtin.Os)) : (i += 1) {
736 comptime const os_tag = @memberName(builtin.Os, i);778 comptime const os_tag = @memberName(builtin.Os, i);
737 // NOTE: Cannot use empty string, see #918.779 // NOTE: Cannot use empty string, see #918.
738 comptime const native_str =780 comptime const native_str = if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
739 if (comptime mem.eql(u8, os_tag, @tagName(builtin.os))) " (native)\n" else "\n";
740781
741 try stdout.print(" {}{}", os_tag, native_str);782 try stdout.print(" {}{}", os_tag, native_str);
742 }783 }
...@@ -749,8 +790,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {...@@ -749,8 +790,7 @@ fn cmdTargets(allocator: &Allocator, args: []const []const u8) !void {
749 inline while (i < @memberCount(builtin.Environ)) : (i += 1) {790 inline while (i < @memberCount(builtin.Environ)) : (i += 1) {
750 comptime const environ_tag = @memberName(builtin.Environ, i);791 comptime const environ_tag = @memberName(builtin.Environ, i);
751 // NOTE: Cannot use empty string, see #918.792 // NOTE: Cannot use empty string, see #918.
752 comptime const native_str =793 comptime const native_str = if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n";
753 if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n";
754794
755 try stdout.print(" {}{}", environ_tag, native_str);795 try stdout.print(" {}{}", environ_tag, native_str);
756 }796 }
...@@ -772,12 +812,9 @@ const usage_test =...@@ -772,12 +812,9 @@ const usage_test =
772 \\ --help Print this help and exit812 \\ --help Print this help and exit
773 \\813 \\
774 \\814 \\
775 ;815;
776
777const args_test_spec = []Flag {
778 Flag.Bool("--help"),
779};
780816
817const args_test_spec = []Flag{Flag.Bool("--help")};
781818
782fn cmdTest(allocator: &Allocator, args: []const []const u8) !void {819fn cmdTest(allocator: &Allocator, args: []const []const u8) !void {
783 var flags = try Args.parse(allocator, args_build_spec, args);820 var flags = try Args.parse(allocator, args_build_spec, args);
...@@ -810,21 +847,18 @@ const usage_run =...@@ -810,21 +847,18 @@ const usage_run =
810 \\ --help Print this help and exit847 \\ --help Print this help and exit
811 \\848 \\
812 \\849 \\
813 ;850;
814
815const args_run_spec = []Flag {
816 Flag.Bool("--help"),
817};
818851
852const args_run_spec = []Flag{Flag.Bool("--help")};
819853
820fn cmdRun(allocator: &Allocator, args: []const []const u8) !void {854fn cmdRun(allocator: &Allocator, args: []const []const u8) !void {
821 var compile_args = args;855 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
824 for (args) |argv, i| {858 for (args) |argv, i| {
825 if (mem.eql(u8, argv, "--")) {859 if (mem.eql(u8, argv, "--")) {
826 compile_args = args[0..i];860 compile_args = args[0..i];
827 runtime_args = args[i+1..];861 runtime_args = args[i + 1..];
828 break;862 break;
829 }863 }
830 }864 }
...@@ -858,9 +892,9 @@ const usage_translate_c =...@@ -858,9 +892,9 @@ const usage_translate_c =
858 \\ --output [path] Output file to write generated zig file (default: stdout)892 \\ --output [path] Output file to write generated zig file (default: stdout)
859 \\893 \\
860 \\894 \\
861 ;895;
862896
863const args_translate_c_spec = []Flag {897const args_translate_c_spec = []Flag{
864 Flag.Bool("--help"),898 Flag.Bool("--help"),
865 Flag.Bool("--enable-timing-info"),899 Flag.Bool("--enable-timing-info"),
866 Flag.Arg1("--libc-include-dir"),900 Flag.Arg1("--libc-include-dir"),
...@@ -934,7 +968,7 @@ const info_zen =...@@ -934,7 +968,7 @@ const info_zen =
934 \\ * Together we serve end users.968 \\ * Together we serve end users.
935 \\969 \\
936 \\970 \\
937 ;971;
938972
939fn cmdZen(allocator: &Allocator, args: []const []const u8) !void {973fn cmdZen(allocator: &Allocator, args: []const []const u8) !void {
940 try stdout.write(info_zen);974 try stdout.write(info_zen);
...@@ -949,7 +983,7 @@ const usage_internal =...@@ -949,7 +983,7 @@ const usage_internal =
949 \\ build-info Print static compiler build-info983 \\ build-info Print static compiler build-info
950 \\984 \\
951 \\985 \\
952 ;986;
953987
954fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {988fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {
955 if (args.len == 0) {989 if (args.len == 0) {
...@@ -957,9 +991,10 @@ fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {...@@ -957,9 +991,10 @@ fn cmdInternal(allocator: &Allocator, args: []const []const u8) !void {
957 os.exit(1);991 os.exit(1);
958 }992 }
959993
960 const sub_commands = []Command {994 const sub_commands = []Command{Command{
961 Command { .name = "build-info", .exec = cmdInternalBuildInfo },995 .name = "build-info",
962 };996 .exec = cmdInternalBuildInfo,
997 }};
963998
964 for (sub_commands) |sub_command| {999 for (sub_commands) |sub_command| {
965 if (mem.eql(u8, sub_command.name, args[0])) {1000 if (mem.eql(u8, sub_command.name, args[0])) {
...@@ -983,7 +1018,7 @@ fn cmdInternalBuildInfo(allocator: &Allocator, args: []const []const u8) !void {...@@ -983,7 +1018,7 @@ fn cmdInternalBuildInfo(allocator: &Allocator, args: []const []const u8) !void {
983 \\ZIG_C_HEADER_FILES {}1018 \\ZIG_C_HEADER_FILES {}
984 \\ZIG_DIA_GUIDS_LIB {}1019 \\ZIG_DIA_GUIDS_LIB {}
985 \\1020 \\
986 ,1021 ,
987 std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),1022 std.cstr.toSliceConst(c.ZIG_CMAKE_BINARY_DIR),
988 std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),1023 std.cstr.toSliceConst(c.ZIG_CXX_COMPILER),
989 std.cstr.toSliceConst(c.ZIG_LLVM_CONFIG_EXE),1024 std.cstr.toSliceConst(c.ZIG_LLVM_CONFIG_EXE),
src-self-hosted/target.zig+1-2
...@@ -38,8 +38,7 @@ pub const Target = union(enum) {...@@ -38,8 +38,7 @@ pub const Target = union(enum) {
3838
39 pub fn isDarwin(self: &const Target) bool {39 pub fn isDarwin(self: &const Target) bool {
40 return switch (self.getOs()) {40 return switch (self.getOs()) {
41 builtin.Os.ios,41 builtin.Os.ios, builtin.Os.macosx => true,
42 builtin.Os.macosx => true,
43 else => false,42 else => false,
44 };43 };
45 }44 }
std/array_list.zig+6-3
...@@ -150,7 +150,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {...@@ -150,7 +150,10 @@ pub fn AlignedArrayList(comptime T: type, comptime A: u29) type {
150 };150 };
151151
152 pub fn iterator(self: &const Self) Iterator {152 pub fn iterator(self: &const Self) Iterator {
153 return Iterator { .list = self, .count = 0 };153 return Iterator{
154 .list = self,
155 .count = 0,
156 };
154 }157 }
155 };158 };
156}159}
...@@ -207,7 +210,7 @@ test "iterator ArrayList test" {...@@ -207,7 +210,7 @@ test "iterator ArrayList test" {
207 try list.append(2);210 try list.append(2);
208 try list.append(3);211 try list.append(3);
209212
210 var count : i32 = 0;213 var count: i32 = 0;
211 var it = list.iterator();214 var it = list.iterator();
212 while (it.next()) |next| {215 while (it.next()) |next| {
213 assert(next == count + 1);216 assert(next == count + 1);
...@@ -225,7 +228,7 @@ test "iterator ArrayList test" {...@@ -225,7 +228,7 @@ test "iterator ArrayList test" {
225 }228 }
226229
227 it.reset();230 it.reset();
228 assert(?? it.next() == 1);231 assert(??it.next() == 1);
229}232}
230233
231test "insert ArrayList test" {234test "insert ArrayList test" {
std/base64.zig+46-71
...@@ -41,12 +41,10 @@ pub const Base64Encoder = struct {...@@ -41,12 +41,10 @@ pub const Base64Encoder = struct {
41 dest[out_index] = encoder.alphabet_chars[(source[i] >> 2) & 0x3f];41 dest[out_index] = encoder.alphabet_chars[(source[i] >> 2) & 0x3f];
42 out_index += 1;42 out_index += 1;
4343
44 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) |44 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)];
45 ((source[i + 1] & 0xf0) >> 4)];
46 out_index += 1;45 out_index += 1;
4746
48 dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) |47 dest[out_index] = encoder.alphabet_chars[((source[i + 1] & 0xf) << 2) | ((source[i + 2] & 0xc0) >> 6)];
49 ((source[i + 2] & 0xc0) >> 6)];
50 out_index += 1;48 out_index += 1;
5149
52 dest[out_index] = encoder.alphabet_chars[source[i + 2] & 0x3f];50 dest[out_index] = encoder.alphabet_chars[source[i + 2] & 0x3f];
...@@ -64,8 +62,7 @@ pub const Base64Encoder = struct {...@@ -64,8 +62,7 @@ pub const Base64Encoder = struct {
64 dest[out_index] = encoder.pad_char;62 dest[out_index] = encoder.pad_char;
65 out_index += 1;63 out_index += 1;
66 } else {64 } else {
67 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) |65 dest[out_index] = encoder.alphabet_chars[((source[i] & 0x3) << 4) | ((source[i + 1] & 0xf0) >> 4)];
68 ((source[i + 1] & 0xf0) >> 4)];
69 out_index += 1;66 out_index += 1;
7067
71 dest[out_index] = encoder.alphabet_chars[(source[i + 1] & 0xf) << 2];68 dest[out_index] = encoder.alphabet_chars[(source[i + 1] & 0xf) << 2];
...@@ -131,26 +128,20 @@ pub const Base64Decoder = struct {...@@ -131,26 +128,20 @@ pub const Base64Decoder = struct {
131 // common case128 // common case
132 if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter;129 if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter;
133 if (!decoder.char_in_alphabet[source[src_cursor + 3]]) return error.InvalidCharacter;130 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 |131 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
135 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;
136 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 |133 dest[dest_cursor + 2] = decoder.char_to_index[source[src_cursor + 2]] << 6 | decoder.char_to_index[source[src_cursor + 3]];
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]];
140 dest_cursor += 3;134 dest_cursor += 3;
141 } else if (source[src_cursor + 2] != decoder.pad_char) {135 } else if (source[src_cursor + 2] != decoder.pad_char) {
142 // one pad char136 // one pad char
143 if (!decoder.char_in_alphabet[source[src_cursor + 2]]) return error.InvalidCharacter;137 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 |138 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
145 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;
146 dest[dest_cursor + 1] = decoder.char_to_index[source[src_cursor + 1]] << 4 |
147 decoder.char_to_index[source[src_cursor + 2]] >> 2;
148 if (decoder.char_to_index[source[src_cursor + 2]] << 6 != 0) return error.InvalidPadding;140 if (decoder.char_to_index[source[src_cursor + 2]] << 6 != 0) return error.InvalidPadding;
149 dest_cursor += 2;141 dest_cursor += 2;
150 } else {142 } else {
151 // two pad chars143 // two pad chars
152 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 |144 dest[dest_cursor + 0] = decoder.char_to_index[source[src_cursor + 0]] << 2 | decoder.char_to_index[source[src_cursor + 1]] >> 4;
153 decoder.char_to_index[source[src_cursor + 1]] >> 4;
154 if (decoder.char_to_index[source[src_cursor + 1]] << 4 != 0) return error.InvalidPadding;145 if (decoder.char_to_index[source[src_cursor + 1]] << 4 != 0) return error.InvalidPadding;
155 dest_cursor += 1;146 dest_cursor += 1;
156 }147 }
...@@ -165,7 +156,7 @@ pub const Base64DecoderWithIgnore = struct {...@@ -165,7 +156,7 @@ pub const Base64DecoderWithIgnore = struct {
165 decoder: Base64Decoder,156 decoder: Base64Decoder,
166 char_is_ignored: [256]bool,157 char_is_ignored: [256]bool,
167 pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {158 pub fn init(alphabet_chars: []const u8, pad_char: u8, ignore_chars: []const u8) Base64DecoderWithIgnore {
168 var result = Base64DecoderWithIgnore {159 var result = Base64DecoderWithIgnore{
169 .decoder = Base64Decoder.init(alphabet_chars, pad_char),160 .decoder = Base64Decoder.init(alphabet_chars, pad_char),
170 .char_is_ignored = []bool{false} ** 256,161 .char_is_ignored = []bool{false} ** 256,
171 };162 };
...@@ -223,10 +214,12 @@ pub const Base64DecoderWithIgnore = struct {...@@ -223,10 +214,12 @@ pub const Base64DecoderWithIgnore = struct {
223 } else if (decoder_with_ignore.char_is_ignored[c]) {214 } else if (decoder_with_ignore.char_is_ignored[c]) {
224 // we can even ignore chars during the padding215 // we can even ignore chars during the padding
225 continue;216 continue;
226 } else return error.InvalidCharacter;217 } else
218 return error.InvalidCharacter;
227 }219 }
228 break;220 break;
229 } else return error.InvalidCharacter;221 } else
222 return error.InvalidCharacter;
230 }223 }
231224
232 switch (available_chars) {225 switch (available_chars) {
...@@ -234,22 +227,17 @@ pub const Base64DecoderWithIgnore = struct {...@@ -234,22 +227,17 @@ pub const Base64DecoderWithIgnore = struct {
234 // common case227 // common case
235 if (dest_cursor + 3 > dest.len) return error.OutputTooSmall;228 if (dest_cursor + 3 > dest.len) return error.OutputTooSmall;
236 assert(pad_char_count == 0);229 assert(pad_char_count == 0);
237 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |230 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
238 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;
239 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 |232 dest[dest_cursor + 2] = decoder.char_to_index[next_4_chars[2]] << 6 | decoder.char_to_index[next_4_chars[3]];
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]];
243 dest_cursor += 3;233 dest_cursor += 3;
244 continue;234 continue;
245 },235 },
246 3 => {236 3 => {
247 if (dest_cursor + 2 > dest.len) return error.OutputTooSmall;237 if (dest_cursor + 2 > dest.len) return error.OutputTooSmall;
248 if (pad_char_count != 1) return error.InvalidPadding;238 if (pad_char_count != 1) return error.InvalidPadding;
249 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |239 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
250 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;
251 dest[dest_cursor + 1] = decoder.char_to_index[next_4_chars[1]] << 4 |
252 decoder.char_to_index[next_4_chars[2]] >> 2;
253 if (decoder.char_to_index[next_4_chars[2]] << 6 != 0) return error.InvalidPadding;241 if (decoder.char_to_index[next_4_chars[2]] << 6 != 0) return error.InvalidPadding;
254 dest_cursor += 2;242 dest_cursor += 2;
255 break;243 break;
...@@ -257,8 +245,7 @@ pub const Base64DecoderWithIgnore = struct {...@@ -257,8 +245,7 @@ pub const Base64DecoderWithIgnore = struct {
257 2 => {245 2 => {
258 if (dest_cursor + 1 > dest.len) return error.OutputTooSmall;246 if (dest_cursor + 1 > dest.len) return error.OutputTooSmall;
259 if (pad_char_count != 2) return error.InvalidPadding;247 if (pad_char_count != 2) return error.InvalidPadding;
260 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 |248 dest[dest_cursor + 0] = decoder.char_to_index[next_4_chars[0]] << 2 | decoder.char_to_index[next_4_chars[1]] >> 4;
261 decoder.char_to_index[next_4_chars[1]] >> 4;
262 if (decoder.char_to_index[next_4_chars[1]] << 4 != 0) return error.InvalidPadding;249 if (decoder.char_to_index[next_4_chars[1]] << 4 != 0) return error.InvalidPadding;
263 dest_cursor += 1;250 dest_cursor += 1;
264 break;251 break;
...@@ -280,7 +267,6 @@ pub const Base64DecoderWithIgnore = struct {...@@ -280,7 +267,6 @@ pub const Base64DecoderWithIgnore = struct {
280 }267 }
281};268};
282269
283
284pub const standard_decoder_unsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, standard_pad_char);270pub const standard_decoder_unsafe = Base64DecoderUnsafe.init(standard_alphabet_chars, standard_pad_char);
285271
286pub const Base64DecoderUnsafe = struct {272pub const Base64DecoderUnsafe = struct {
...@@ -291,7 +277,7 @@ pub const Base64DecoderUnsafe = struct {...@@ -291,7 +277,7 @@ pub const Base64DecoderUnsafe = struct {
291277
292 pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe {278 pub fn init(alphabet_chars: []const u8, pad_char: u8) Base64DecoderUnsafe {
293 assert(alphabet_chars.len == 64);279 assert(alphabet_chars.len == 64);
294 var result = Base64DecoderUnsafe {280 var result = Base64DecoderUnsafe{
295 .char_to_index = undefined,281 .char_to_index = undefined,
296 .pad_char = pad_char,282 .pad_char = pad_char,
297 };283 };
...@@ -321,16 +307,13 @@ pub const Base64DecoderUnsafe = struct {...@@ -321,16 +307,13 @@ pub const Base64DecoderUnsafe = struct {
321 }307 }
322308
323 while (in_buf_len > 4) {309 while (in_buf_len > 4) {
324 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 |310 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4;
325 decoder.char_to_index[source[src_index + 1]] >> 4;
326 dest_index += 1;311 dest_index += 1;
327312
328 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 |313 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2;
329 decoder.char_to_index[source[src_index + 2]] >> 2;
330 dest_index += 1;314 dest_index += 1;
331315
332 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 |316 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]];
333 decoder.char_to_index[source[src_index + 3]];
334 dest_index += 1;317 dest_index += 1;
335318
336 src_index += 4;319 src_index += 4;
...@@ -338,18 +321,15 @@ pub const Base64DecoderUnsafe = struct {...@@ -338,18 +321,15 @@ pub const Base64DecoderUnsafe = struct {
338 }321 }
339322
340 if (in_buf_len > 1) {323 if (in_buf_len > 1) {
341 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 |324 dest[dest_index] = decoder.char_to_index[source[src_index + 0]] << 2 | decoder.char_to_index[source[src_index + 1]] >> 4;
342 decoder.char_to_index[source[src_index + 1]] >> 4;
343 dest_index += 1;325 dest_index += 1;
344 }326 }
345 if (in_buf_len > 2) {327 if (in_buf_len > 2) {
346 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 |328 dest[dest_index] = decoder.char_to_index[source[src_index + 1]] << 4 | decoder.char_to_index[source[src_index + 2]] >> 2;
347 decoder.char_to_index[source[src_index + 2]] >> 2;
348 dest_index += 1;329 dest_index += 1;
349 }330 }
350 if (in_buf_len > 3) {331 if (in_buf_len > 3) {
351 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 |332 dest[dest_index] = decoder.char_to_index[source[src_index + 2]] << 6 | decoder.char_to_index[source[src_index + 3]];
352 decoder.char_to_index[source[src_index + 3]];
353 dest_index += 1;333 dest_index += 1;
354 }334 }
355 }335 }
...@@ -367,7 +347,6 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize {...@@ -367,7 +347,6 @@ fn calcDecodedSizeExactUnsafe(source: []const u8, pad_char: u8) usize {
367 return result;347 return result;
368}348}
369349
370
371test "base64" {350test "base64" {
372 @setEvalBranchQuota(8000);351 @setEvalBranchQuota(8000);
373 testBase64() catch unreachable;352 testBase64() catch unreachable;
...@@ -375,26 +354,26 @@ test "base64" {...@@ -375,26 +354,26 @@ test "base64" {
375}354}
376355
377fn testBase64() !void {356fn testBase64() !void {
378 try testAllApis("", "");357 try testAllApis("", "");
379 try testAllApis("f", "Zg==");358 try testAllApis("f", "Zg==");
380 try testAllApis("fo", "Zm8=");359 try testAllApis("fo", "Zm8=");
381 try testAllApis("foo", "Zm9v");360 try testAllApis("foo", "Zm9v");
382 try testAllApis("foob", "Zm9vYg==");361 try testAllApis("foob", "Zm9vYg==");
383 try testAllApis("fooba", "Zm9vYmE=");362 try testAllApis("fooba", "Zm9vYmE=");
384 try testAllApis("foobar", "Zm9vYmFy");363 try testAllApis("foobar", "Zm9vYmFy");
385364
386 try testDecodeIgnoreSpace("", " ");365 try testDecodeIgnoreSpace("", " ");
387 try testDecodeIgnoreSpace("f", "Z g= =");366 try testDecodeIgnoreSpace("f", "Z g= =");
388 try testDecodeIgnoreSpace("fo", " Zm8=");367 try testDecodeIgnoreSpace("fo", " Zm8=");
389 try testDecodeIgnoreSpace("foo", "Zm9v ");368 try testDecodeIgnoreSpace("foo", "Zm9v ");
390 try testDecodeIgnoreSpace("foob", "Zm9vYg = = ");369 try testDecodeIgnoreSpace("foob", "Zm9vYg = = ");
391 try testDecodeIgnoreSpace("fooba", "Zm9v YmE=");370 try testDecodeIgnoreSpace("fooba", "Zm9v YmE=");
392 try testDecodeIgnoreSpace("foobar", " Z m 9 v Y m F y ");371 try testDecodeIgnoreSpace("foobar", " Z m 9 v Y m F y ");
393372
394 // test getting some api errors373 // test getting some api errors
395 try testError("A", error.InvalidPadding);374 try testError("A", error.InvalidPadding);
396 try testError("AA", error.InvalidPadding);375 try testError("AA", error.InvalidPadding);
397 try testError("AAA", error.InvalidPadding);376 try testError("AAA", error.InvalidPadding);
398 try testError("A..A", error.InvalidCharacter);377 try testError("A..A", error.InvalidCharacter);
399 try testError("AA=A", error.InvalidCharacter);378 try testError("AA=A", error.InvalidCharacter);
400 try testError("AA/=", error.InvalidPadding);379 try testError("AA/=", error.InvalidPadding);
...@@ -427,8 +406,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void...@@ -427,8 +406,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
427406
428 // Base64DecoderWithIgnore407 // Base64DecoderWithIgnore
429 {408 {
430 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(409 const standard_decoder_ignore_nothing = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, "");
431 standard_alphabet_chars, standard_pad_char, "");
432 var buffer: [0x100]u8 = undefined;410 var buffer: [0x100]u8 = undefined;
433 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];411 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(expected_encoded.len)];
434 var written = try standard_decoder_ignore_nothing.decode(decoded, expected_encoded);412 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...@@ -446,8 +424,7 @@ fn testAllApis(expected_decoded: []const u8, expected_encoded: []const u8) !void
446}424}
447425
448fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !void {426fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !void {
449 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(427 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
450 standard_alphabet_chars, standard_pad_char, " ");
451 var buffer: [0x100]u8 = undefined;428 var buffer: [0x100]u8 = undefined;
452 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];429 var decoded = buffer[0..Base64DecoderWithIgnore.calcSizeUpperBound(encoded.len)];
453 var written = try standard_decoder_ignore_space.decode(decoded, encoded);430 var written = try standard_decoder_ignore_space.decode(decoded, encoded);
...@@ -455,8 +432,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi...@@ -455,8 +432,7 @@ fn testDecodeIgnoreSpace(expected_decoded: []const u8, encoded: []const u8) !voi
455}432}
456433
457fn testError(encoded: []const u8, expected_err: error) !void {434fn testError(encoded: []const u8, expected_err: error) !void {
458 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(435 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
459 standard_alphabet_chars, standard_pad_char, " ");
460 var buffer: [0x100]u8 = undefined;436 var buffer: [0x100]u8 = undefined;
461 if (standard_decoder.calcSize(encoded)) |decoded_size| {437 if (standard_decoder.calcSize(encoded)) |decoded_size| {
462 var decoded = buffer[0..decoded_size];438 var decoded = buffer[0..decoded_size];
...@@ -471,8 +447,7 @@ fn testError(encoded: []const u8, expected_err: error) !void {...@@ -471,8 +447,7 @@ fn testError(encoded: []const u8, expected_err: error) !void {
471}447}
472448
473fn testOutputTooSmallError(encoded: []const u8) !void {449fn testOutputTooSmallError(encoded: []const u8) !void {
474 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(450 const standard_decoder_ignore_space = Base64DecoderWithIgnore.init(standard_alphabet_chars, standard_pad_char, " ");
475 standard_alphabet_chars, standard_pad_char, " ");
476 var buffer: [0x100]u8 = undefined;451 var buffer: [0x100]u8 = undefined;
477 var decoded = buffer[0..calcDecodedSizeExactUnsafe(encoded, standard_pad_char) - 1];452 var decoded = buffer[0..calcDecodedSizeExactUnsafe(encoded, standard_pad_char) - 1];
478 if (standard_decoder_ignore_space.decode(decoded, encoded)) |_| {453 if (standard_decoder_ignore_space.decode(decoded, encoded)) |_| {
std/buf_map.zig+1-3
...@@ -12,9 +12,7 @@ pub const BufMap = struct {...@@ -12,9 +12,7 @@ pub const BufMap = struct {
12 const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);12 const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);
1313
14 pub fn init(allocator: &Allocator) BufMap {14 pub fn init(allocator: &Allocator) BufMap {
15 var self = BufMap {15 var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) };
16 .hash_map = BufMapHashMap.init(allocator),
17 };
18 return self;16 return self;
19 }17 }
2018
std/buf_set.zig+1-3
...@@ -10,9 +10,7 @@ pub const BufSet = struct {...@@ -10,9 +10,7 @@ pub const BufSet = struct {
10 const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);10 const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
1111
12 pub fn init(a: &Allocator) BufSet {12 pub fn init(a: &Allocator) BufSet {
13 var self = BufSet {13 var self = BufSet{ .hash_map = BufSetHashMap.init(a) };
14 .hash_map = BufSetHashMap.init(a),
15 };
16 return self;14 return self;
17 }15 }
1816
std/build.zig+21-38
...@@ -420,15 +420,7 @@ pub const Builder = struct {...@@ -420,15 +420,7 @@ pub const Builder = struct {
420 const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false;420 const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false;
421 const release_small = self.option(bool, "release-small", "size optimizations on and safety off") ?? false;421 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)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: {
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: {
432 warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)");424 warn("Multiple release modes (of -Drelease-safe, -Drelease-fast and -Drelease-small)");
433 self.markInvalidUserInput();425 self.markInvalidUserInput();
434 break :x builtin.Mode.Debug;426 break :x builtin.Mode.Debug;
...@@ -649,11 +641,7 @@ pub const Builder = struct {...@@ -649,11 +641,7 @@ pub const Builder = struct {
649 if (builtin.environ == builtin.Environ.msvc) {641 if (builtin.environ == builtin.Environ.msvc) {
650 return "cl.exe";642 return "cl.exe";
651 } else {643 } else {
652 return os.getEnvVarOwned(self.allocator, "CC") catch |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);
653 if (err == error.EnvironmentVariableNotFound)
654 ([]const u8)("cc")
655 else
656 debug.panic("Unable to get environment variable: {}", err);
657 }645 }
658 }646 }
659647
...@@ -782,8 +770,7 @@ pub const Target = union(enum) {...@@ -782,8 +770,7 @@ pub const Target = union(enum) {
782770
783 pub fn isDarwin(self: &const Target) bool {771 pub fn isDarwin(self: &const Target) bool {
784 return switch (self.getOs()) {772 return switch (self.getOs()) {
785 builtin.Os.ios,773 builtin.Os.ios, builtin.Os.macosx => true,
786 builtin.Os.macosx => true,
787 else => false,774 else => false,
788 };775 };
789 }776 }
...@@ -990,8 +977,7 @@ pub const LibExeObjStep = struct {...@@ -990,8 +977,7 @@ pub const LibExeObjStep = struct {
990 self.out_filename = self.builder.fmt("lib{}.a", self.name);977 self.out_filename = self.builder.fmt("lib{}.a", self.name);
991 } else {978 } else {
992 switch (self.target.getOs()) {979 switch (self.target.getOs()) {
993 builtin.Os.ios,980 builtin.Os.ios, builtin.Os.macosx => {
994 builtin.Os.macosx => {
995 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);981 self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", self.name, self.version.major, self.version.minor, self.version.patch);
996 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);982 self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", self.name, self.version.major);
997 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);983 self.name_only_filename = self.builder.fmt("lib{}.dylib", self.name);
...@@ -1011,11 +997,13 @@ pub const LibExeObjStep = struct {...@@ -1011,11 +997,13 @@ pub const LibExeObjStep = struct {
1011 }997 }
1012998
1013 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {999 pub fn setTarget(self: &LibExeObjStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1014 self.target = Target{ .Cross = CrossTarget{1000 self.target = Target{
1015 .arch = target_arch,1001 .Cross = CrossTarget{
1016 .os = target_os,1002 .arch = target_arch,
1017 .environ = target_environ,1003 .os = target_os,
1018 } };1004 .environ = target_environ,
1005 },
1006 };
1019 self.computeOutFileNames();1007 self.computeOutFileNames();
1020 }1008 }
10211009
...@@ -1079,10 +1067,7 @@ pub const LibExeObjStep = struct {...@@ -1079,10 +1067,7 @@ pub const LibExeObjStep = struct {
1079 }1067 }
10801068
1081 pub fn getOutputPath(self: &LibExeObjStep) []const u8 {1069 pub fn getOutputPath(self: &LibExeObjStep) []const u8 {
1082 return if (self.output_path) |output_path|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;
1083 output_path
1084 else
1085 os.path.join(self.builder.allocator, self.builder.cache_root, self.out_filename) catch unreachable;
1086 }1071 }
10871072
1088 pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void {1073 pub fn setOutputHPath(self: &LibExeObjStep, file_path: []const u8) void {
...@@ -1095,10 +1080,7 @@ pub const LibExeObjStep = struct {...@@ -1095,10 +1080,7 @@ pub const LibExeObjStep = struct {
1095 }1080 }
10961081
1097 pub fn getOutputHPath(self: &LibExeObjStep) []const u8 {1082 pub fn getOutputHPath(self: &LibExeObjStep) []const u8 {
1098 return if (self.output_h_path) |output_h_path|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;
1099 output_h_path
1100 else
1101 os.path.join(self.builder.allocator, self.builder.cache_root, self.out_h_filename) catch unreachable;
1102 }1084 }
11031085
1104 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void {1086 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) void {
...@@ -1352,8 +1334,7 @@ pub const LibExeObjStep = struct {...@@ -1352,8 +1334,7 @@ pub const LibExeObjStep = struct {
1352 args.append("ssp-buffer-size=4") catch unreachable;1334 args.append("ssp-buffer-size=4") catch unreachable;
1353 }1335 }
1354 },1336 },
1355 builtin.Mode.ReleaseFast,1337 builtin.Mode.ReleaseFast, builtin.Mode.ReleaseSmall => {
1356 builtin.Mode.ReleaseSmall => {
1357 args.append("-O2") catch unreachable;1338 args.append("-O2") catch unreachable;
1358 args.append("-fno-stack-protector") catch unreachable;1339 args.append("-fno-stack-protector") catch unreachable;
1359 },1340 },
...@@ -1652,11 +1633,13 @@ pub const TestStep = struct {...@@ -1652,11 +1633,13 @@ pub const TestStep = struct {
1652 }1633 }
16531634
1654 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {1635 pub fn setTarget(self: &TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
1655 self.target = Target{ .Cross = CrossTarget{1636 self.target = Target{
1656 .arch = target_arch,1637 .Cross = CrossTarget{
1657 .os = target_os,1638 .arch = target_arch,
1658 .environ = target_environ,1639 .os = target_os,
1659 } };1640 .environ = target_environ,
1641 },
1642 };
1660 }1643 }
16611644
1662 pub fn setExecCmd(self: &TestStep, args: []const ?[]const u8) void {1645 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;...@@ -60,7 +60,7 @@ pub const sigset_t = u32;
6060
61/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.61/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
62pub const Sigaction = extern struct {62pub const Sigaction = extern struct {
63 handler: extern fn(c_int)void,63 handler: extern fn(c_int) void,
64 sa_mask: sigset_t,64 sa_mask: sigset_t,
65 sa_flags: c_int,65 sa_flags: c_int,
66};66};
std/c/index.zig+4-8
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const Os = builtin.Os;2const Os = builtin.Os;
33
4pub use switch(builtin.os) {4pub use switch (builtin.os) {
5 Os.linux => @import("linux.zig"),5 Os.linux => @import("linux.zig"),
6 Os.windows => @import("windows.zig"),6 Os.windows => @import("windows.zig"),
7 Os.macosx, Os.ios => @import("darwin.zig"),7 Os.macosx, Os.ios => @import("darwin.zig"),
...@@ -21,8 +21,7 @@ pub extern "c" fn raise(sig: c_int) c_int;...@@ -21,8 +21,7 @@ pub extern "c" fn raise(sig: c_int) c_int;
21pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize;21pub extern "c" fn read(fd: c_int, buf: &c_void, nbyte: usize) isize;
22pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int;22pub extern "c" fn stat(noalias path: &const u8, noalias buf: &Stat) c_int;
23pub extern "c" fn write(fd: c_int, buf: &const c_void, nbyte: usize) isize;23pub 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,24pub extern "c" fn mmap(addr: ?&c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?&c_void;
25 fd: c_int, offset: isize) ?&c_void;
26pub extern "c" fn munmap(addr: &c_void, len: usize) c_int;25pub extern "c" fn munmap(addr: &c_void, len: usize) c_int;
27pub extern "c" fn unlink(path: &const u8) c_int;26pub extern "c" fn unlink(path: &const u8) c_int;
28pub extern "c" fn getcwd(buf: &u8, size: usize) ?&u8;27pub 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;...@@ -34,8 +33,7 @@ pub extern "c" fn mkdir(path: &const u8, mode: c_uint) c_int;
34pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;33pub extern "c" fn symlink(existing: &const u8, new: &const u8) c_int;
35pub extern "c" fn rename(old: &const u8, new: &const u8) c_int;34pub extern "c" fn rename(old: &const u8, new: &const u8) c_int;
36pub extern "c" fn chdir(path: &const u8) c_int;35pub extern "c" fn chdir(path: &const u8) c_int;
37pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8,36pub extern "c" fn execve(path: &const u8, argv: &const ?&const u8, envp: &const ?&const u8) c_int;
38 envp: &const ?&const u8) c_int;
39pub extern "c" fn dup(fd: c_int) c_int;37pub extern "c" fn dup(fd: c_int) c_int;
40pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;38pub extern "c" fn dup2(old_fd: c_int, new_fd: c_int) c_int;
41pub extern "c" fn readlink(noalias path: &const u8, noalias buf: &u8, bufsize: usize) isize;39pub 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;...@@ -54,9 +52,7 @@ pub extern "c" fn realloc(&c_void, usize) ?&c_void;
54pub extern "c" fn free(&c_void) void;52pub extern "c" fn free(&c_void) void;
55pub extern "c" fn posix_memalign(memptr: &&c_void, alignment: usize, size: usize) c_int;53pub 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,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;
58 noalias attr: ?&const pthread_attr_t, start_routine: extern fn(?&c_void) ?&c_void,
59 noalias arg: ?&c_void) c_int;
60pub extern "pthread" fn pthread_attr_init(attr: &pthread_attr_t) c_int;56pub extern "pthread" fn pthread_attr_init(attr: &pthread_attr_t) c_int;
61pub extern "pthread" fn pthread_attr_setstack(attr: &pthread_attr_t, stackaddr: &c_void, stacksize: usize) c_int;57pub extern "pthread" fn pthread_attr_setstack(attr: &pthread_attr_t, stackaddr: &c_void, stacksize: usize) c_int;
62pub extern "pthread" fn pthread_attr_destroy(attr: &pthread_attr_t) c_int;58pub 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");...@@ -6,12 +6,25 @@ const debug = @import("../debug/index.zig");
6const fmt = @import("../fmt/index.zig");6const fmt = @import("../fmt/index.zig");
77
8const RoundParam = struct {8const RoundParam = struct {
9 a: usize, b: usize, c: usize, d: usize,9 a: usize,
10 k: usize, s: u32, t: u3210 b: usize,
11 c: usize,
12 d: usize,
13 k: usize,
14 s: u32,
15 t: u32,
11};16};
1217
13fn Rp(a: usize, b: usize, c: usize, d: usize, k: usize, s: u32, t: u32) RoundParam {18fn 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 };
15}28}
1629
17pub const Md5 = struct {30pub const Md5 = struct {
...@@ -99,7 +112,7 @@ pub const Md5 = struct {...@@ -99,7 +112,7 @@ pub const Md5 = struct {
99 d.round(d.buf[0..]);112 d.round(d.buf[0..]);
100113
101 for (d.s) |s, j| {114 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);
103 }116 }
104 }117 }
105118
...@@ -112,30 +125,33 @@ pub const Md5 = struct {...@@ -112,30 +125,33 @@ pub const Md5 = struct {
112 while (i < 16) : (i += 1) {125 while (i < 16) : (i += 1) {
113 // NOTE: Performing or's separately improves perf by ~10%126 // NOTE: Performing or's separately improves perf by ~10%
114 s[i] = 0;127 s[i] = 0;
115 s[i] |= u32(b[i*4+0]);128 s[i] |= u32(b[i * 4 + 0]);
116 s[i] |= u32(b[i*4+1]) << 8;129 s[i] |= u32(b[i * 4 + 1]) << 8;
117 s[i] |= u32(b[i*4+2]) << 16;130 s[i] |= u32(b[i * 4 + 2]) << 16;
118 s[i] |= u32(b[i*4+3]) << 24;131 s[i] |= u32(b[i * 4 + 3]) << 24;
119 }132 }
120133
121 var v: [4]u32 = []u32 {134 var v: [4]u32 = []u32{
122 d.s[0], d.s[1], d.s[2], d.s[3],135 d.s[0],
136 d.s[1],
137 d.s[2],
138 d.s[3],
123 };139 };
124140
125 const round0 = comptime []RoundParam {141 const round0 = comptime []RoundParam{
126 Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),142 Rp(0, 1, 2, 3, 0, 7, 0xD76AA478),
127 Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),143 Rp(3, 0, 1, 2, 1, 12, 0xE8C7B756),
128 Rp(2, 3, 0, 1, 2, 17, 0x242070DB),144 Rp(2, 3, 0, 1, 2, 17, 0x242070DB),
129 Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE),145 Rp(1, 2, 3, 0, 3, 22, 0xC1BDCEEE),
130 Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF),146 Rp(0, 1, 2, 3, 4, 7, 0xF57C0FAF),
131 Rp(3, 0, 1, 2, 5, 12, 0x4787C62A),147 Rp(3, 0, 1, 2, 5, 12, 0x4787C62A),
132 Rp(2, 3, 0, 1, 6, 17, 0xA8304613),148 Rp(2, 3, 0, 1, 6, 17, 0xA8304613),
133 Rp(1, 2, 3, 0, 7, 22, 0xFD469501),149 Rp(1, 2, 3, 0, 7, 22, 0xFD469501),
134 Rp(0, 1, 2, 3, 8, 7, 0x698098D8),150 Rp(0, 1, 2, 3, 8, 7, 0x698098D8),
135 Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF),151 Rp(3, 0, 1, 2, 9, 12, 0x8B44F7AF),
136 Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1),152 Rp(2, 3, 0, 1, 10, 17, 0xFFFF5BB1),
137 Rp(1, 2, 3, 0, 11, 22, 0x895CD7BE),153 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),
139 Rp(3, 0, 1, 2, 13, 12, 0xFD987193),155 Rp(3, 0, 1, 2, 13, 12, 0xFD987193),
140 Rp(2, 3, 0, 1, 14, 17, 0xA679438E),156 Rp(2, 3, 0, 1, 14, 17, 0xA679438E),
141 Rp(1, 2, 3, 0, 15, 22, 0x49B40821),157 Rp(1, 2, 3, 0, 15, 22, 0x49B40821),
...@@ -145,22 +161,22 @@ pub const Md5 = struct {...@@ -145,22 +161,22 @@ pub const Md5 = struct {
145 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);161 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
146 }162 }
147163
148 const round1 = comptime []RoundParam {164 const round1 = comptime []RoundParam{
149 Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),165 Rp(0, 1, 2, 3, 1, 5, 0xF61E2562),
150 Rp(3, 0, 1, 2, 6, 9, 0xC040B340),166 Rp(3, 0, 1, 2, 6, 9, 0xC040B340),
151 Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),167 Rp(2, 3, 0, 1, 11, 14, 0x265E5A51),
152 Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA),168 Rp(1, 2, 3, 0, 0, 20, 0xE9B6C7AA),
153 Rp(0, 1, 2, 3, 5, 5, 0xD62F105D),169 Rp(0, 1, 2, 3, 5, 5, 0xD62F105D),
154 Rp(3, 0, 1, 2, 10, 9, 0x02441453),170 Rp(3, 0, 1, 2, 10, 9, 0x02441453),
155 Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681),171 Rp(2, 3, 0, 1, 15, 14, 0xD8A1E681),
156 Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8),172 Rp(1, 2, 3, 0, 4, 20, 0xE7D3FBC8),
157 Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6),173 Rp(0, 1, 2, 3, 9, 5, 0x21E1CDE6),
158 Rp(3, 0, 1, 2, 14, 9, 0xC33707D6),174 Rp(3, 0, 1, 2, 14, 9, 0xC33707D6),
159 Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87),175 Rp(2, 3, 0, 1, 3, 14, 0xF4D50D87),
160 Rp(1, 2, 3, 0, 8, 20, 0x455A14ED),176 Rp(1, 2, 3, 0, 8, 20, 0x455A14ED),
161 Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905),177 Rp(0, 1, 2, 3, 13, 5, 0xA9E3E905),
162 Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8),178 Rp(3, 0, 1, 2, 2, 9, 0xFCEFA3F8),
163 Rp(2, 3, 0, 1, 7, 14, 0x676F02D9),179 Rp(2, 3, 0, 1, 7, 14, 0x676F02D9),
164 Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A),180 Rp(1, 2, 3, 0, 12, 20, 0x8D2A4C8A),
165 };181 };
166 inline for (round1) |r| {182 inline for (round1) |r| {
...@@ -168,46 +184,46 @@ pub const Md5 = struct {...@@ -168,46 +184,46 @@ pub const Md5 = struct {
168 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);184 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
169 }185 }
170186
171 const round2 = comptime []RoundParam {187 const round2 = comptime []RoundParam{
172 Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),188 Rp(0, 1, 2, 3, 5, 4, 0xFFFA3942),
173 Rp(3, 0, 1, 2, 8, 11, 0x8771F681),189 Rp(3, 0, 1, 2, 8, 11, 0x8771F681),
174 Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),190 Rp(2, 3, 0, 1, 11, 16, 0x6D9D6122),
175 Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C),191 Rp(1, 2, 3, 0, 14, 23, 0xFDE5380C),
176 Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44),192 Rp(0, 1, 2, 3, 1, 4, 0xA4BEEA44),
177 Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9),193 Rp(3, 0, 1, 2, 4, 11, 0x4BDECFA9),
178 Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60),194 Rp(2, 3, 0, 1, 7, 16, 0xF6BB4B60),
179 Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70),195 Rp(1, 2, 3, 0, 10, 23, 0xBEBFBC70),
180 Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6),196 Rp(0, 1, 2, 3, 13, 4, 0x289B7EC6),
181 Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA),197 Rp(3, 0, 1, 2, 0, 11, 0xEAA127FA),
182 Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085),198 Rp(2, 3, 0, 1, 3, 16, 0xD4EF3085),
183 Rp(1, 2, 3, 0, 6, 23, 0x04881D05),199 Rp(1, 2, 3, 0, 6, 23, 0x04881D05),
184 Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039),200 Rp(0, 1, 2, 3, 9, 4, 0xD9D4D039),
185 Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5),201 Rp(3, 0, 1, 2, 12, 11, 0xE6DB99E5),
186 Rp(2, 3, 0, 1, 15, 16, 0x1FA27CF8),202 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),
188 };204 };
189 inline for (round2) |r| {205 inline for (round2) |r| {
190 v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k];206 v[r.a] = v[r.a] +% (v[r.b] ^ v[r.c] ^ v[r.d]) +% r.t +% s[r.k];
191 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);207 v[r.a] = v[r.b] +% math.rotl(u32, v[r.a], r.s);
192 }208 }
193209
194 const round3 = comptime []RoundParam {210 const round3 = comptime []RoundParam{
195 Rp(0, 1, 2, 3, 0, 6, 0xF4292244),211 Rp(0, 1, 2, 3, 0, 6, 0xF4292244),
196 Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),212 Rp(3, 0, 1, 2, 7, 10, 0x432AFF97),
197 Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),213 Rp(2, 3, 0, 1, 14, 15, 0xAB9423A7),
198 Rp(1, 2, 3, 0, 5, 21, 0xFC93A039),214 Rp(1, 2, 3, 0, 5, 21, 0xFC93A039),
199 Rp(0, 1, 2, 3, 12, 6, 0x655B59C3),215 Rp(0, 1, 2, 3, 12, 6, 0x655B59C3),
200 Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92),216 Rp(3, 0, 1, 2, 3, 10, 0x8F0CCC92),
201 Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D),217 Rp(2, 3, 0, 1, 10, 15, 0xFFEFF47D),
202 Rp(1, 2, 3, 0, 1, 21, 0x85845DD1),218 Rp(1, 2, 3, 0, 1, 21, 0x85845DD1),
203 Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F),219 Rp(0, 1, 2, 3, 8, 6, 0x6FA87E4F),
204 Rp(3, 0, 1, 2, 15, 10, 0xFE2CE6E0),220 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),
206 Rp(1, 2, 3, 0, 13, 21, 0x4E0811A1),222 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),
208 Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235),224 Rp(3, 0, 1, 2, 11, 10, 0xBD3AF235),
209 Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB),225 Rp(2, 3, 0, 1, 2, 15, 0x2AD7D2BB),
210 Rp(1, 2, 3, 0, 9, 21, 0xEB86D391),226 Rp(1, 2, 3, 0, 9, 21, 0xEB86D391),
211 };227 };
212 inline for (round3) |r| {228 inline for (round3) |r| {
213 v[r.a] = v[r.a] +% (v[r.c] ^ (v[r.b] | ~v[r.d])) +% r.t +% s[r.k];229 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" {...@@ -255,7 +271,7 @@ test "md5 streaming" {
255}271}
256272
257test "md5 aligned final" {273test "md5 aligned final" {
258 var block = []u8 {0} ** Md5.block_size;274 var block = []u8{0} ** Md5.block_size;
259 var out: [Md5.digest_size]u8 = undefined;275 var out: [Md5.digest_size]u8 = undefined;
260276
261 var h = Md5.init();277 var h = Md5.init();
std/crypto/sha1.zig+47-39
...@@ -7,11 +7,23 @@ const builtin = @import("builtin");...@@ -7,11 +7,23 @@ const builtin = @import("builtin");
7pub const u160 = @IntType(false, 160);7pub const u160 = @IntType(false, 160);
88
9const RoundParam = struct {9const 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,
11};16};
1217
13fn Rp(a: usize, b: usize, c: usize, d: usize, e: usize, i: u32) RoundParam {18fn 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 };
15}27}
1628
17pub const Sha1 = struct {29pub const Sha1 = struct {
...@@ -99,7 +111,7 @@ pub const Sha1 = struct {...@@ -99,7 +111,7 @@ pub const Sha1 = struct {
99 d.round(d.buf[0..]);111 d.round(d.buf[0..]);
100112
101 for (d.s) |s, j| {113 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);
103 }115 }
104 }116 }
105117
...@@ -108,21 +120,25 @@ pub const Sha1 = struct {...@@ -108,21 +120,25 @@ pub const Sha1 = struct {
108120
109 var s: [16]u32 = undefined;121 var s: [16]u32 = undefined;
110122
111 var v: [5]u32 = []u32 {123 var v: [5]u32 = []u32{
112 d.s[0], d.s[1], d.s[2], d.s[3], d.s[4],124 d.s[0],
125 d.s[1],
126 d.s[2],
127 d.s[3],
128 d.s[4],
113 };129 };
114130
115 const round0a = comptime []RoundParam {131 const round0a = comptime []RoundParam{
116 Rp(0, 1, 2, 3, 4, 0),132 Rp(0, 1, 2, 3, 4, 0),
117 Rp(4, 0, 1, 2, 3, 1),133 Rp(4, 0, 1, 2, 3, 1),
118 Rp(3, 4, 0, 1, 2, 2),134 Rp(3, 4, 0, 1, 2, 2),
119 Rp(2, 3, 4, 0, 1, 3),135 Rp(2, 3, 4, 0, 1, 3),
120 Rp(1, 2, 3, 4, 0, 4),136 Rp(1, 2, 3, 4, 0, 4),
121 Rp(0, 1, 2, 3, 4, 5),137 Rp(0, 1, 2, 3, 4, 5),
122 Rp(4, 0, 1, 2, 3, 6),138 Rp(4, 0, 1, 2, 3, 6),
123 Rp(3, 4, 0, 1, 2, 7),139 Rp(3, 4, 0, 1, 2, 7),
124 Rp(2, 3, 4, 0, 1, 8),140 Rp(2, 3, 4, 0, 1, 8),
125 Rp(1, 2, 3, 4, 0, 9),141 Rp(1, 2, 3, 4, 0, 9),
126 Rp(0, 1, 2, 3, 4, 10),142 Rp(0, 1, 2, 3, 4, 10),
127 Rp(4, 0, 1, 2, 3, 11),143 Rp(4, 0, 1, 2, 3, 11),
128 Rp(3, 4, 0, 1, 2, 12),144 Rp(3, 4, 0, 1, 2, 12),
...@@ -131,32 +147,27 @@ pub const Sha1 = struct {...@@ -131,32 +147,27 @@ pub const Sha1 = struct {
131 Rp(0, 1, 2, 3, 4, 15),147 Rp(0, 1, 2, 3, 4, 15),
132 };148 };
133 inline for (round0a) |r| {149 inline for (round0a) |r| {
134 s[r.i] = (u32(b[r.i * 4 + 0]) << 24) |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);
135 (u32(b[r.i * 4 + 1]) << 16) |
136 (u32(b[r.i * 4 + 2]) << 8) |
137 (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]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]));
140 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
141 v[r.b] = math.rotl(u32, v[r.b], u32(30));153 v[r.b] = math.rotl(u32, v[r.b], u32(30));
142 }154 }
143155
144 const round0b = comptime []RoundParam {156 const round0b = comptime []RoundParam{
145 Rp(4, 0, 1, 2, 3, 16),157 Rp(4, 0, 1, 2, 3, 16),
146 Rp(3, 4, 0, 1, 2, 17),158 Rp(3, 4, 0, 1, 2, 17),
147 Rp(2, 3, 4, 0, 1, 18),159 Rp(2, 3, 4, 0, 1, 18),
148 Rp(1, 2, 3, 4, 0, 19),160 Rp(1, 2, 3, 4, 0, 19),
149 };161 };
150 inline for (round0b) |r| {162 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];
152 s[r.i & 0xf] = math.rotl(u32, t, u32(1));164 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]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]));
155 +% ((v[r.b] & v[r.c]) | (~v[r.b] & v[r.d]));
156 v[r.b] = math.rotl(u32, v[r.b], u32(30));167 v[r.b] = math.rotl(u32, v[r.b], u32(30));
157 }168 }
158169
159 const round1 = comptime []RoundParam {170 const round1 = comptime []RoundParam{
160 Rp(0, 1, 2, 3, 4, 20),171 Rp(0, 1, 2, 3, 4, 20),
161 Rp(4, 0, 1, 2, 3, 21),172 Rp(4, 0, 1, 2, 3, 21),
162 Rp(3, 4, 0, 1, 2, 22),173 Rp(3, 4, 0, 1, 2, 22),
...@@ -179,15 +190,14 @@ pub const Sha1 = struct {...@@ -179,15 +190,14 @@ pub const Sha1 = struct {
179 Rp(1, 2, 3, 4, 0, 39),190 Rp(1, 2, 3, 4, 0, 39),
180 };191 };
181 inline for (round1) |r| {192 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];
183 s[r.i & 0xf] = math.rotl(u32, t, u32(1));194 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]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]);
186 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
187 v[r.b] = math.rotl(u32, v[r.b], u32(30));197 v[r.b] = math.rotl(u32, v[r.b], u32(30));
188 }198 }
189199
190 const round2 = comptime []RoundParam {200 const round2 = comptime []RoundParam{
191 Rp(0, 1, 2, 3, 4, 40),201 Rp(0, 1, 2, 3, 4, 40),
192 Rp(4, 0, 1, 2, 3, 41),202 Rp(4, 0, 1, 2, 3, 41),
193 Rp(3, 4, 0, 1, 2, 42),203 Rp(3, 4, 0, 1, 2, 42),
...@@ -210,15 +220,14 @@ pub const Sha1 = struct {...@@ -210,15 +220,14 @@ pub const Sha1 = struct {
210 Rp(1, 2, 3, 4, 0, 59),220 Rp(1, 2, 3, 4, 0, 59),
211 };221 };
212 inline for (round2) |r| {222 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];
214 s[r.i & 0xf] = math.rotl(u32, t, u32(1));224 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]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]));
217 +% ((v[r.b] & v[r.c]) ^ (v[r.b] & v[r.d]) ^ (v[r.c] & v[r.d]));
218 v[r.b] = math.rotl(u32, v[r.b], u32(30));227 v[r.b] = math.rotl(u32, v[r.b], u32(30));
219 }228 }
220229
221 const round3 = comptime []RoundParam {230 const round3 = comptime []RoundParam{
222 Rp(0, 1, 2, 3, 4, 60),231 Rp(0, 1, 2, 3, 4, 60),
223 Rp(4, 0, 1, 2, 3, 61),232 Rp(4, 0, 1, 2, 3, 61),
224 Rp(3, 4, 0, 1, 2, 62),233 Rp(3, 4, 0, 1, 2, 62),
...@@ -241,11 +250,10 @@ pub const Sha1 = struct {...@@ -241,11 +250,10 @@ pub const Sha1 = struct {
241 Rp(1, 2, 3, 4, 0, 79),250 Rp(1, 2, 3, 4, 0, 79),
242 };251 };
243 inline for (round3) |r| {252 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];
245 s[r.i & 0xf] = math.rotl(u32, t, u32(1));254 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]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]);
248 +% (v[r.b] ^ v[r.c] ^ v[r.d]);
249 v[r.b] = math.rotl(u32, v[r.b], u32(30));257 v[r.b] = math.rotl(u32, v[r.b], u32(30));
250 }258 }
251259
...@@ -286,7 +294,7 @@ test "sha1 streaming" {...@@ -286,7 +294,7 @@ test "sha1 streaming" {
286}294}
287295
288test "sha1 aligned final" {296test "sha1 aligned final" {
289 var block = []u8 {0} ** Sha1.block_size;297 var block = []u8{0} ** Sha1.block_size;
290 var out: [Sha1.digest_size]u8 = undefined;298 var out: [Sha1.digest_size]u8 = undefined;
291299
292 var h = Sha1.init();300 var h = Sha1.init();
std/crypto/sha2.zig+448-413
...@@ -9,12 +9,31 @@ const htest = @import("test.zig");...@@ -9,12 +9,31 @@ const htest = @import("test.zig");
9// Sha224 + Sha2569// Sha224 + Sha256
1010
11const RoundParam256 = struct {11const RoundParam256 = struct {
12 a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize,12 a: usize,
13 i: usize, k: u32,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,
14};22};
1523
16fn Rp256(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u32) RoundParam256 {24fn 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 };
18}37}
1938
20const Sha2Params32 = struct {39const Sha2Params32 = struct {
...@@ -29,7 +48,7 @@ const Sha2Params32 = struct {...@@ -29,7 +48,7 @@ const Sha2Params32 = struct {
29 out_len: usize,48 out_len: usize,
30};49};
3150
32const Sha224Params = Sha2Params32 {51const Sha224Params = Sha2Params32{
33 .iv0 = 0xC1059ED8,52 .iv0 = 0xC1059ED8,
34 .iv1 = 0x367CD507,53 .iv1 = 0x367CD507,
35 .iv2 = 0x3070DD17,54 .iv2 = 0x3070DD17,
...@@ -41,7 +60,7 @@ const Sha224Params = Sha2Params32 {...@@ -41,7 +60,7 @@ const Sha224Params = Sha2Params32 {
41 .out_len = 224,60 .out_len = 224,
42};61};
4362
44const Sha256Params = Sha2Params32 {63const Sha256Params = Sha2Params32{
45 .iv0 = 0x6A09E667,64 .iv0 = 0x6A09E667,
46 .iv1 = 0xBB67AE85,65 .iv1 = 0xBB67AE85,
47 .iv2 = 0x3C6EF372,66 .iv2 = 0x3C6EF372,
...@@ -56,216 +75,215 @@ const Sha256Params = Sha2Params32 {...@@ -56,216 +75,215 @@ const Sha256Params = Sha2Params32 {
56pub const Sha224 = Sha2_32(Sha224Params);75pub const Sha224 = Sha2_32(Sha224Params);
57pub const Sha256 = Sha2_32(Sha256Params);76pub const Sha256 = Sha2_32(Sha256Params);
5877
59fn Sha2_32(comptime params: Sha2Params32) type { return struct {78fn Sha2_32(comptime params: Sha2Params32) type {
60 const Self = this;79 return struct {
61 const block_size = 64;80 const Self = this;
62 const digest_size = params.out_len / 8;81 const block_size = 64;
6382 const digest_size = params.out_len / 8;
64 s: [8]u32,83
65 // Streaming Cache84 s: [8]u32,
66 buf: [64]u8,85 // Streaming Cache
67 buf_len: u8,86 buf: [64]u8,
68 total_len: u64,87 buf_len: u8,
6988 total_len: u64,
70 pub fn init() Self {89
71 var d: Self = undefined;90 pub fn init() Self {
72 d.reset();91 var d: Self = undefined;
73 return d;92 d.reset();
74 }93 return d;
7594 }
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]);
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;
104 d.buf_len = 0;105 d.buf_len = 0;
106 d.total_len = 0;
105 }107 }
106108
107 // Full middle blocks.109 pub fn hash(b: []const u8, out: []u8) void {
108 while (off + 64 <= b.len) : (off += 64) {110 var d = Self.init();
109 d.round(b[off..off + 64]);111 d.update(b);
112 d.final(out);
110 }113 }
111114
112 // Copy any remainder for next pass.115 pub fn update(d: &Self, b: []const u8) void {
113 mem.copy(u8, d.buf[d.buf_len..], b[off..]);116 var off: usize = 0;
114 d.buf_len += u8(b[off..].len);
115117
116 d.total_len += b.len;118 // Partial buffer exists from previous update. Copy into buffer then hash.
117 }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 {123 d.round(d.buf[0..]);
120 debug.assert(out.len >= params.out_len / 8);124 d.buf_len = 0;
125 }
121126
122 // The buffer here will never be completely full.127 // Full middle blocks.
123 mem.set(u8, d.buf[d.buf_len..], 0);128 while (off + 64 <= b.len) : (off += 64) {
129 d.round(b[off..off + 64]);
130 }
124131
125 // Append padding bits.132 // Copy any remainder for next pass.
126 d.buf[d.buf_len] = 0x80;133 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
127 d.buf_len += 1;134 d.buf_len += u8(b[off..].len);
128135
129 // > 448 mod 512 so need to add an extra round to wrap around.136 d.total_len += b.len;
130 if (64 - d.buf_len < 8) {
131 d.round(d.buf[0..]);
132 mem.set(u8, d.buf[0..], 0);
133 }137 }
134138
135 // Append message length.139 pub fn final(d: &Self, out: []u8) void {
136 var i: usize = 1;140 debug.assert(out.len >= params.out_len / 8);
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 }
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 output145 // Append padding bits.
147 const rr = d.s[0 .. params.out_len / 32];146 d.buf[d.buf_len] = 0x80;
147 d.buf_len += 1;
148148
149 for (rr) |s, j| {149 // > 448 mod 512 so need to add an extra round to wrap around.
150 mem.writeInt(out[4*j .. 4*j + 4], s, builtin.Endian.Big);150 if (64 - d.buf_len < 8) {
151 }151 d.round(d.buf[0..]);
152 }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 {164 d.round(d.buf[0..]);
155 debug.assert(b.len == 64);
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;169 for (rr) |s, j| {
160 while (i < 16) : (i += 1) {170 mem.writeInt(out[4 * j..4 * j + 4], s, builtin.Endian.Big);
161 s[i] = 0;171 }
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));
172 }172 }
173173
174 var v: [8]u32 = []u32 {174 fn round(d: &Self, b: []const u8) void {
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],175 debug.assert(b.len == 64);
176 };176
177177 var s: [64]u32 = undefined;
178 const round0 = comptime []RoundParam256 {178
179 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),179 var i: usize = 0;
180 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),180 while (i < 16) : (i += 1) {
181 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),181 s[i] = 0;
182 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5),182 s[i] |= u32(b[i * 4 + 0]) << 24;
183 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B),183 s[i] |= u32(b[i * 4 + 1]) << 16;
184 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1),184 s[i] |= u32(b[i * 4 + 2]) << 8;
185 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4),185 s[i] |= u32(b[i * 4 + 3]) << 0;
186 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5),186 }
187 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98),187 while (i < 64) : (i += 1) {
188 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01),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 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE),189 }
190 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3),190
191 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74),191 var v: [8]u32 = []u32{
192 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE),192 d.s[0],
193 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7),193 d.s[1],
194 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174),194 d.s[2],
195 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1),195 d.s[3],
196 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786),196 d.s[4],
197 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6),197 d.s[5],
198 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC),198 d.s[6],
199 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F),199 d.s[7],
200 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA),200 };
201 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC),201
202 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA),202 const round0 = comptime []RoundParam256{
203 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152),203 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98),
204 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D),204 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x71374491),
205 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8),205 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCF),
206 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7),206 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA5),
207 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3),207 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25B),
208 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147),208 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1),
209 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351),209 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4),
210 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967),210 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5),
211 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85),211 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98),
212 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138),212 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B01),
213 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC),213 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE),
214 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13),214 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3),
215 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354),215 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 12, 0x72BE5D74),
216 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB),216 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 13, 0x80DEB1FE),
217 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E),217 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 14, 0x9BDC06A7),
218 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85),218 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 15, 0xC19BF174),
219 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1),219 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 16, 0xE49B69C1),
220 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B),220 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 17, 0xEFBE4786),
221 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70),221 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 18, 0x0FC19DC6),
222 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3),222 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 19, 0x240CA1CC),
223 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819),223 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 20, 0x2DE92C6F),
224 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624),224 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 21, 0x4A7484AA),
225 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585),225 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 22, 0x5CB0A9DC),
226 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070),226 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 23, 0x76F988DA),
227 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116),227 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 24, 0x983E5152),
228 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08),228 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 25, 0xA831C66D),
229 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C),229 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 26, 0xB00327C8),
230 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5),230 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 27, 0xBF597FC7),
231 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3),231 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 28, 0xC6E00BF3),
232 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 53, 0x4ED8AA4A),232 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 29, 0xD5A79147),
233 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 54, 0x5B9CCA4F),233 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 30, 0x06CA6351),
234 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 55, 0x682E6FF3),234 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 31, 0x14292967),
235 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 56, 0x748F82EE),235 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 32, 0x27B70A85),
236 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 57, 0x78A5636F),236 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 33, 0x2E1B2138),
237 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 58, 0x84C87814),237 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 34, 0x4D2C6DFC),
238 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 59, 0x8CC70208),238 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 35, 0x53380D13),
239 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 60, 0x90BEFFFA),239 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 36, 0x650A7354),
240 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 61, 0xA4506CEB),240 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 37, 0x766A0ABB),
241 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 62, 0xBEF9A3F7),241 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 38, 0x81C2C92E),
242 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 63, 0xC67178F2),242 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 39, 0x92722C85),
243 };243 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 40, 0xA2BFE8A1),
244 inline for (round0) |r| {244 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 41, 0xA81A664B),
245 v[r.h] =245 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 42, 0xC24B8B70),
246 v[r.h] +%246 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 43, 0xC76C51A3),
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))) +%247 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 44, 0xD192E819),
248 (v[r.g] ^ (v[r.e] & (v[r.f] ^ v[r.g]))) +%248 Rp256(3, 4, 5, 6, 7, 0, 1, 2, 45, 0xD6990624),
249 r.k +% s[r.i];249 Rp256(2, 3, 4, 5, 6, 7, 0, 1, 46, 0xF40E3585),
250250 Rp256(1, 2, 3, 4, 5, 6, 7, 0, 47, 0x106AA070),
251 v[r.d] = v[r.d] +% v[r.h];251 Rp256(0, 1, 2, 3, 4, 5, 6, 7, 48, 0x19A4C116),
252252 Rp256(7, 0, 1, 2, 3, 4, 5, 6, 49, 0x1E376C08),
253 v[r.h] =253 Rp256(6, 7, 0, 1, 2, 3, 4, 5, 50, 0x2748774C),
254 v[r.h] +%254 Rp256(5, 6, 7, 0, 1, 2, 3, 4, 51, 0x34B0BCB5),
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))) +%255 Rp256(4, 5, 6, 7, 0, 1, 2, 3, 52, 0x391C0CB3),
256 ((v[r.a] & (v[r.b] | v[r.c])) | (v[r.b] & v[r.c]));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];
257 }284 }
258285 };
259 d.s[0] +%= v[0];286}
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};}
269287
270test "sha224 single" {288test "sha224 single" {
271 htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "");289 htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", "");
...@@ -320,7 +338,7 @@ test "sha256 streaming" {...@@ -320,7 +338,7 @@ test "sha256 streaming" {
320}338}
321339
322test "sha256 aligned final" {340test "sha256 aligned final" {
323 var block = []u8 {0} ** Sha256.block_size;341 var block = []u8{0} ** Sha256.block_size;
324 var out: [Sha256.digest_size]u8 = undefined;342 var out: [Sha256.digest_size]u8 = undefined;
325343
326 var h = Sha256.init();344 var h = Sha256.init();
...@@ -328,17 +346,35 @@ test "sha256 aligned final" {...@@ -328,17 +346,35 @@ test "sha256 aligned final" {
328 h.final(out[0..]);346 h.final(out[0..]);
329}347}
330348
331
332/////////////////////349/////////////////////
333// Sha384 + Sha512350// Sha384 + Sha512
334351
335const RoundParam512 = struct {352const RoundParam512 = struct {
336 a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize,353 a: usize,
337 i: usize, k: u64,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,
338};363};
339364
340fn Rp512(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: usize, k: u64) RoundParam512 {365fn 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 };
342}378}
343379
344const Sha2Params64 = struct {380const Sha2Params64 = struct {
...@@ -353,7 +389,7 @@ const Sha2Params64 = struct {...@@ -353,7 +389,7 @@ const Sha2Params64 = struct {
353 out_len: usize,389 out_len: usize,
354};390};
355391
356const Sha384Params = Sha2Params64 {392const Sha384Params = Sha2Params64{
357 .iv0 = 0xCBBB9D5DC1059ED8,393 .iv0 = 0xCBBB9D5DC1059ED8,
358 .iv1 = 0x629A292A367CD507,394 .iv1 = 0x629A292A367CD507,
359 .iv2 = 0x9159015A3070DD17,395 .iv2 = 0x9159015A3070DD17,
...@@ -365,7 +401,7 @@ const Sha384Params = Sha2Params64 {...@@ -365,7 +401,7 @@ const Sha384Params = Sha2Params64 {
365 .out_len = 384,401 .out_len = 384,
366};402};
367403
368const Sha512Params = Sha2Params64 {404const Sha512Params = Sha2Params64{
369 .iv0 = 0x6A09E667F3BCC908,405 .iv0 = 0x6A09E667F3BCC908,
370 .iv1 = 0xBB67AE8584CAA73B,406 .iv1 = 0xBB67AE8584CAA73B,
371 .iv2 = 0x3C6EF372FE94F82B,407 .iv2 = 0x3C6EF372FE94F82B,
...@@ -374,242 +410,241 @@ const Sha512Params = Sha2Params64 {...@@ -374,242 +410,241 @@ const Sha512Params = Sha2Params64 {
374 .iv5 = 0x9B05688C2B3E6C1F,410 .iv5 = 0x9B05688C2B3E6C1F,
375 .iv6 = 0x1F83D9ABFB41BD6B,411 .iv6 = 0x1F83D9ABFB41BD6B,
376 .iv7 = 0x5BE0CD19137E2179,412 .iv7 = 0x5BE0CD19137E2179,
377 .out_len = 512413 .out_len = 512,
378};414};
379415
380pub const Sha384 = Sha2_64(Sha384Params);416pub const Sha384 = Sha2_64(Sha384Params);
381pub const Sha512 = Sha2_64(Sha512Params);417pub const Sha512 = Sha2_64(Sha512Params);
382418
383fn Sha2_64(comptime params: Sha2Params64) type { return struct {419fn Sha2_64(comptime params: Sha2Params64) type {
384 const Self = this;420 return struct {
385 const block_size = 128;421 const Self = this;
386 const digest_size = params.out_len / 8;422 const block_size = 128;
387423 const digest_size = params.out_len / 8;
388 s: [8]u64,424
389 // Streaming Cache425 s: [8]u64,
390 buf: [128]u8,426 // Streaming Cache
391 buf_len: u8,427 buf: [128]u8,
392 total_len: u128,428 buf_len: u8,
393429 total_len: u128,
394 pub fn init() Self {430
395 var d: Self = undefined;431 pub fn init() Self {
396 d.reset();432 var d: Self = undefined;
397 return d;433 d.reset();
398 }434 return d;
399435 }
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]);
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;
428 d.buf_len = 0;446 d.buf_len = 0;
447 d.total_len = 0;
429 }448 }
430449
431 // Full middle blocks.450 pub fn hash(b: []const u8, out: []u8) void {
432 while (off + 128 <= b.len) : (off += 128) {451 var d = Self.init();
433 d.round(b[off..off + 128]);452 d.update(b);
453 d.final(out);
434 }454 }
435455
436 // Copy any remainder for next pass.456 pub fn update(d: &Self, b: []const u8) void {
437 mem.copy(u8, d.buf[d.buf_len..], b[off..]);457 var off: usize = 0;
438 d.buf_len += u8(b[off..].len);
439458
440 d.total_len += b.len;459 // Partial buffer exists from previous update. Copy into buffer then hash.
441 }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 {464 d.round(d.buf[0..]);
444 debug.assert(out.len >= params.out_len / 8);465 d.buf_len = 0;
466 }
445467
446 // The buffer here will never be completely full.468 // Full middle blocks.
447 mem.set(u8, d.buf[d.buf_len..], 0);469 while (off + 128 <= b.len) : (off += 128) {
470 d.round(b[off..off + 128]);
471 }
448472
449 // Append padding bits.473 // Copy any remainder for next pass.
450 d.buf[d.buf_len] = 0x80;474 mem.copy(u8, d.buf[d.buf_len..], b[off..]);
451 d.buf_len += 1;475 d.buf_len += u8(b[off..].len);
452476
453 // > 896 mod 1024 so need to add an extra round to wrap around.477 d.total_len += b.len;
454 if (128 - d.buf_len < 16) {
455 d.round(d.buf[0..]);
456 mem.set(u8, d.buf[0..], 0);
457 }478 }
458479
459 // Append message length.480 pub fn final(d: &Self, out: []u8) void {
460 var i: usize = 1;481 debug.assert(out.len >= params.out_len / 8);
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 }
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 output486 // Append padding bits.
471 const rr = d.s[0 .. params.out_len / 64];487 d.buf[d.buf_len] = 0x80;
488 d.buf_len += 1;
472489
473 for (rr) |s, j| {490 // > 896 mod 1024 so need to add an extra round to wrap around.
474 mem.writeInt(out[8*j .. 8*j + 8], s, builtin.Endian.Big);491 if (128 - d.buf_len < 16) {
475 }492 d.round(d.buf[0..]);
476 }493 mem.set(u8, d.buf[0..], 0);
477494 }
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 }
501495
502 var v: [8]u64 = []u64 {496 // Append message length.
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],497 var i: usize = 1;
504 };498 var len = d.total_len >> 5;
505499 d.buf[127] = u8(d.total_len & 0x1f) << 3;
506 const round0 = comptime []RoundParam512 {500 while (i < 16) : (i += 1) {
507 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 0, 0x428A2F98D728AE22),501 d.buf[127 - i] = u8(len & 0xff);
508 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 1, 0x7137449123EF65CD),502 len >>= 8;
509 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 2, 0xB5C0FBCFEC4D3B2F),503 }
510 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 3, 0xE9B5DBA58189DBBC),504
511 Rp512(4, 5, 6, 7, 0, 1, 2, 3, 4, 0x3956C25BF348B538),505 d.round(d.buf[0..]);
512 Rp512(3, 4, 5, 6, 7, 0, 1, 2, 5, 0x59F111F1B605D019),506
513 Rp512(2, 3, 4, 5, 6, 7, 0, 1, 6, 0x923F82A4AF194F9B),507 // May truncate for possible 384 output
514 Rp512(1, 2, 3, 4, 5, 6, 7, 0, 7, 0xAB1C5ED5DA6D8118),508 const rr = d.s[0..params.out_len / 64];
515 Rp512(0, 1, 2, 3, 4, 5, 6, 7, 8, 0xD807AA98A3030242),509
516 Rp512(7, 0, 1, 2, 3, 4, 5, 6, 9, 0x12835B0145706FBE),510 for (rr) |s, j| {
517 Rp512(6, 7, 0, 1, 2, 3, 4, 5, 10, 0x243185BE4EE4B28C),511 mem.writeInt(out[8 * j..8 * j + 8], s, builtin.Endian.Big);
518 Rp512(5, 6, 7, 0, 1, 2, 3, 4, 11, 0x550C7DC3D5FFB4E2),512 }
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]));
601 }513 }
602514
603 d.s[0] +%= v[0];515 fn round(d: &Self, b: []const u8) void {
604 d.s[1] +%= v[1];516 debug.assert(b.len == 128);
605 d.s[2] +%= v[2];517
606 d.s[3] +%= v[3];518 var s: [80]u64 = undefined;
607 d.s[4] +%= v[4];519
608 d.s[5] +%= v[5];520 var i: usize = 0;
609 d.s[6] +%= v[6];521 while (i < 16) : (i += 1) {
610 d.s[7] +%= v[7];522 s[i] = 0;
611 }523 s[i] |= u64(b[i * 8 + 0]) << 56;
612};}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
614test "sha384 single" {649test "sha384 single" {
615 const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";650 const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";
...@@ -680,7 +715,7 @@ test "sha512 streaming" {...@@ -680,7 +715,7 @@ test "sha512 streaming" {
680}715}
681716
682test "sha512 aligned final" {717test "sha512 aligned final" {
683 var block = []u8 {0} ** Sha512.block_size;718 var block = []u8{0} ** Sha512.block_size;
684 var out: [Sha512.digest_size]u8 = undefined;719 var out: [Sha512.digest_size]u8 = undefined;
685720
686 var h = Sha512.init();721 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...@@ -14,7 +14,7 @@ pub fn assertEqualHash(comptime Hasher: var, comptime expected: []const u8, inpu
14pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {14pub fn assertEqual(comptime expected: []const u8, input: []const u8) void {
15 var expected_bytes: [expected.len / 2]u8 = undefined;15 var expected_bytes: [expected.len / 2]u8 = undefined;
16 for (expected_bytes) |*r, i| {16 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;
18 }18 }
1919
20 debug.assert(mem.eql(u8, expected_bytes, input));20 debug.assert(mem.eql(u8, expected_bytes, input));
std/crypto/throughput_test.zig+1-1
...@@ -11,7 +11,7 @@ const Timer = time.Timer;...@@ -11,7 +11,7 @@ const Timer = time.Timer;
11const HashFunction = @import("md5.zig").Md5;11const HashFunction = @import("md5.zig").Md5;
1212
13const MiB = 1024 * 1024;13const MiB = 1024 * 1024;
14const BytesToHash = 1024 * MiB;14const BytesToHash = 1024 * MiB;
1515
16pub fn main() !void {16pub fn main() !void {
17 var stdout_file = try std.io.getStdOut();17 var stdout_file = try std.io.getStdOut();
std/cstr.zig+1-3
...@@ -9,7 +9,6 @@ pub const line_sep = switch (builtin.os) {...@@ -9,7 +9,6 @@ pub const line_sep = switch (builtin.os) {
9 else => "\n",9 else => "\n",
10};10};
1111
12
13pub fn len(ptr: &const u8) usize {12pub fn len(ptr: &const u8) usize {
14 var count: usize = 0;13 var count: usize = 0;
15 while (ptr[count] != 0) : (count += 1) {}14 while (ptr[count] != 0) : (count += 1) {}
...@@ -95,7 +94,7 @@ pub const NullTerminated2DArray = struct {...@@ -95,7 +94,7 @@ pub const NullTerminated2DArray = struct {
95 }94 }
96 index_buf[i] = null;95 index_buf[i] = null;
9796
98 return NullTerminated2DArray {97 return NullTerminated2DArray{
99 .allocator = allocator,98 .allocator = allocator,
100 .byte_count = byte_count,99 .byte_count = byte_count,
101 .ptr = @ptrCast(?&?&u8, buf.ptr),100 .ptr = @ptrCast(?&?&u8, buf.ptr),
...@@ -107,4 +106,3 @@ pub const NullTerminated2DArray = struct {...@@ -107,4 +106,3 @@ pub const NullTerminated2DArray = struct {
107 self.allocator.free(buf[0..self.byte_count]);106 self.allocator.free(buf[0..self.byte_count]);
108 }107 }
109};108};
110
std/debug/failing_allocator.zig+2-2
...@@ -13,14 +13,14 @@ pub const FailingAllocator = struct {...@@ -13,14 +13,14 @@ pub const FailingAllocator = struct {
13 deallocations: usize,13 deallocations: usize,
1414
15 pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator {15 pub fn init(allocator: &mem.Allocator, fail_index: usize) FailingAllocator {
16 return FailingAllocator {16 return FailingAllocator{
17 .internal_allocator = allocator,17 .internal_allocator = allocator,
18 .fail_index = fail_index,18 .fail_index = fail_index,
19 .index = 0,19 .index = 0,
20 .allocated_bytes = 0,20 .allocated_bytes = 0,
21 .freed_bytes = 0,21 .freed_bytes = 0,
22 .deallocations = 0,22 .deallocations = 0,
23 .allocator = mem.Allocator {23 .allocator = mem.Allocator{
24 .allocFn = alloc,24 .allocFn = alloc,
25 .reallocFn = realloc,25 .reallocFn = realloc,
26 .freeFn = free,26 .freeFn = free,
std/debug/index.zig+9-9
...@@ -227,8 +227,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us...@@ -227,8 +227,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: var, address: us
227 else => return err,227 else => return err,
228 }228 }
229 } else |err| switch (err) {229 } else |err| switch (err) {
230 error.MissingDebugInfo,230 error.MissingDebugInfo, error.InvalidDebugInfo => {
231 error.InvalidDebugInfo => {
232 try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name);231 try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name);
233 },232 },
234 else => return err,233 else => return err,
...@@ -597,10 +596,12 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !...@@ -597,10 +596,12 @@ fn parseFormValueBlock(allocator: &mem.Allocator, in_stream: var, size: usize) !
597}596}
598597
599fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {598fn parseFormValueConstant(allocator: &mem.Allocator, in_stream: var, signed: bool, size: usize) !FormValue {
600 return FormValue{ .Const = Constant{599 return FormValue{
601 .signed = signed,600 .Const = Constant{
602 .payload = try readAllocBytes(allocator, in_stream, size),601 .signed = signed,
603 } };602 .payload = try readAllocBytes(allocator, in_stream, size),
603 },
604 };
604}605}
605606
606fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {607fn parseFormValueDwarfOffsetSize(in_stream: var, is_64: bool) !u64 {
...@@ -621,7 +622,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type...@@ -621,7 +622,7 @@ fn parseFormValueRef(allocator: &mem.Allocator, in_stream: var, comptime T: type
621 return parseFormValueRefLen(allocator, in_stream, block_len);622 return parseFormValueRefLen(allocator, in_stream, block_len);
622}623}
623624
624const ParseFormValueError = error {625const ParseFormValueError = error{
625 EndOfStream,626 EndOfStream,
626 Io,627 Io,
627 BadFd,628 BadFd,
...@@ -645,8 +646,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -645,8 +646,7 @@ fn parseFormValue(allocator: &mem.Allocator, in_stream: var, form_id: u64, is_64
645 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),646 DW.FORM_data2 => parseFormValueConstant(allocator, in_stream, false, 2),
646 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),647 DW.FORM_data4 => parseFormValueConstant(allocator, in_stream, false, 4),
647 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),648 DW.FORM_data8 => parseFormValueConstant(allocator, in_stream, false, 8),
648 DW.FORM_udata,649 DW.FORM_udata, DW.FORM_sdata => {
649 DW.FORM_sdata => {
650 const block_len = try readULeb128(in_stream);650 const block_len = try readULeb128(in_stream);
651 const signed = form_id == DW.FORM_sdata;651 const signed = form_id == DW.FORM_sdata;
652 return parseFormValueConstant(allocator, in_stream, signed, block_len);652 return parseFormValueConstant(allocator, in_stream, signed, block_len);
std/dwarf.zig-2
...@@ -337,7 +337,6 @@ pub const AT_PGI_lbase = 0x3a00;...@@ -337,7 +337,6 @@ pub const AT_PGI_lbase = 0x3a00;
337pub const AT_PGI_soffset = 0x3a01;337pub const AT_PGI_soffset = 0x3a01;
338pub const AT_PGI_lstride = 0x3a02;338pub const AT_PGI_lstride = 0x3a02;
339339
340
341pub const OP_addr = 0x03;340pub const OP_addr = 0x03;
342pub const OP_deref = 0x06;341pub const OP_deref = 0x06;
343pub const OP_const1u = 0x08;342pub const OP_const1u = 0x08;
...@@ -577,7 +576,6 @@ pub const ATE_HP_unsigned_fixed = 0x8e; // Cobol....@@ -577,7 +576,6 @@ pub const ATE_HP_unsigned_fixed = 0x8e; // Cobol.
577pub const ATE_HP_VAX_complex_float = 0x8f; // F or G floating complex.576pub const ATE_HP_VAX_complex_float = 0x8f; // F or G floating complex.
578pub const ATE_HP_VAX_complex_float_d = 0x90; // D floating complex.577pub const ATE_HP_VAX_complex_float_d = 0x90; // D floating complex.
579578
580
581pub const CFA_advance_loc = 0x40;579pub const CFA_advance_loc = 0x40;
582pub const CFA_offset = 0x80;580pub const CFA_offset = 0x80;
583pub const CFA_restore = 0xc0;581pub const CFA_restore = 0xc0;
std/elf.zig+17-25
...@@ -123,13 +123,11 @@ pub const DT_SYMINFO = 0x6ffffeff;...@@ -123,13 +123,11 @@ pub const DT_SYMINFO = 0x6ffffeff;
123pub const DT_ADDRRNGHI = 0x6ffffeff;123pub const DT_ADDRRNGHI = 0x6ffffeff;
124pub const DT_ADDRNUM = 11;124pub const DT_ADDRNUM = 11;
125125
126
127pub const DT_VERSYM = 0x6ffffff0;126pub const DT_VERSYM = 0x6ffffff0;
128127
129pub const DT_RELACOUNT = 0x6ffffff9;128pub const DT_RELACOUNT = 0x6ffffff9;
130pub const DT_RELCOUNT = 0x6ffffffa;129pub const DT_RELCOUNT = 0x6ffffffa;
131130
132
133pub const DT_FLAGS_1 = 0x6ffffffb;131pub const DT_FLAGS_1 = 0x6ffffffb;
134pub const DT_VERDEF = 0x6ffffffc;132pub const DT_VERDEF = 0x6ffffffc;
135133
...@@ -139,13 +137,10 @@ pub const DT_VERNEED = 0x6ffffffe;...@@ -139,13 +137,10 @@ pub const DT_VERNEED = 0x6ffffffe;
139pub const DT_VERNEEDNUM = 0x6fffffff;137pub const DT_VERNEEDNUM = 0x6fffffff;
140pub const DT_VERSIONTAGNUM = 16;138pub const DT_VERSIONTAGNUM = 16;
141139
142
143
144pub const DT_AUXILIARY = 0x7ffffffd;140pub const DT_AUXILIARY = 0x7ffffffd;
145pub const DT_FILTER = 0x7fffffff;141pub const DT_FILTER = 0x7fffffff;
146pub const DT_EXTRANUM = 3;142pub const DT_EXTRANUM = 3;
147143
148
149pub const DT_SPARC_REGISTER = 0x70000001;144pub const DT_SPARC_REGISTER = 0x70000001;
150pub const DT_SPARC_NUM = 2;145pub const DT_SPARC_NUM = 2;
151146
...@@ -434,9 +429,7 @@ pub const Elf = struct {...@@ -434,9 +429,7 @@ pub const Elf = struct {
434 try elf.in_file.seekForward(4);429 try elf.in_file.seekForward(4);
435430
436 const header_size = try in.readInt(elf.endian, u16);431 const header_size = try in.readInt(elf.endian, u16);
437 if ((elf.is_64 and header_size != 64) or432 if ((elf.is_64 and header_size != 64) or (!elf.is_64 and header_size != 52)) {
438 (!elf.is_64 and header_size != 52))
439 {
440 return error.InvalidFormat;433 return error.InvalidFormat;
441 }434 }
442435
...@@ -467,16 +460,16 @@ pub const Elf = struct {...@@ -467,16 +460,16 @@ pub const Elf = struct {
467 if (sh_entry_size != 64) return error.InvalidFormat;460 if (sh_entry_size != 64) return error.InvalidFormat;
468461
469 for (elf.section_headers) |*elf_section| {462 for (elf.section_headers) |*elf_section| {
470 elf_section.name = try in.readInt(elf.endian, u32);463 elf_section.name = try in.readInt(elf.endian, u32);
471 elf_section.sh_type = try in.readInt(elf.endian, u32);464 elf_section.sh_type = try in.readInt(elf.endian, u32);
472 elf_section.flags = try in.readInt(elf.endian, u64);465 elf_section.flags = try in.readInt(elf.endian, u64);
473 elf_section.addr = try in.readInt(elf.endian, u64);466 elf_section.addr = try in.readInt(elf.endian, u64);
474 elf_section.offset = try in.readInt(elf.endian, u64);467 elf_section.offset = try in.readInt(elf.endian, u64);
475 elf_section.size = try in.readInt(elf.endian, u64);468 elf_section.size = try in.readInt(elf.endian, u64);
476 elf_section.link = try in.readInt(elf.endian, u32);469 elf_section.link = try in.readInt(elf.endian, u32);
477 elf_section.info = try in.readInt(elf.endian, u32);470 elf_section.info = try in.readInt(elf.endian, u32);
478 elf_section.addr_align = try in.readInt(elf.endian, u64);471 elf_section.addr_align = try in.readInt(elf.endian, u64);
479 elf_section.ent_size = try in.readInt(elf.endian, u64);472 elf_section.ent_size = try in.readInt(elf.endian, u64);
480 }473 }
481 } else {474 } else {
482 if (sh_entry_size != 40) return error.InvalidFormat;475 if (sh_entry_size != 40) return error.InvalidFormat;
...@@ -513,8 +506,7 @@ pub const Elf = struct {...@@ -513,8 +506,7 @@ pub const Elf = struct {
513 pub fn close(elf: &Elf) void {506 pub fn close(elf: &Elf) void {
514 elf.allocator.free(elf.section_headers);507 elf.allocator.free(elf.section_headers);
515508
516 if (elf.auto_close_stream)509 if (elf.auto_close_stream) elf.in_file.close();
517 elf.in_file.close();
518 }510 }
519511
520 pub fn findSection(elf: &Elf, name: []const u8) !?&SectionHeader {512 pub fn findSection(elf: &Elf, name: []const u8) !?&SectionHeader {
...@@ -852,27 +844,27 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct {...@@ -852,27 +844,27 @@ pub const Elf_MIPS_ABIFlags_v0 = extern struct {
852 flags2: Elf32_Word,844 flags2: Elf32_Word,
853};845};
854846
855pub const Ehdr = switch(@sizeOf(usize)) {847pub const Ehdr = switch (@sizeOf(usize)) {
856 4 => Elf32_Ehdr,848 4 => Elf32_Ehdr,
857 8 => Elf64_Ehdr,849 8 => Elf64_Ehdr,
858 else => @compileError("expected pointer size of 32 or 64"),850 else => @compileError("expected pointer size of 32 or 64"),
859};851};
860pub const Phdr = switch(@sizeOf(usize)) {852pub const Phdr = switch (@sizeOf(usize)) {
861 4 => Elf32_Phdr,853 4 => Elf32_Phdr,
862 8 => Elf64_Phdr,854 8 => Elf64_Phdr,
863 else => @compileError("expected pointer size of 32 or 64"),855 else => @compileError("expected pointer size of 32 or 64"),
864};856};
865pub const Sym = switch(@sizeOf(usize)) {857pub const Sym = switch (@sizeOf(usize)) {
866 4 => Elf32_Sym,858 4 => Elf32_Sym,
867 8 => Elf64_Sym,859 8 => Elf64_Sym,
868 else => @compileError("expected pointer size of 32 or 64"),860 else => @compileError("expected pointer size of 32 or 64"),
869};861};
870pub const Verdef = switch(@sizeOf(usize)) {862pub const Verdef = switch (@sizeOf(usize)) {
871 4 => Elf32_Verdef,863 4 => Elf32_Verdef,
872 8 => Elf64_Verdef,864 8 => Elf64_Verdef,
873 else => @compileError("expected pointer size of 32 or 64"),865 else => @compileError("expected pointer size of 32 or 64"),
874};866};
875pub const Verdaux = switch(@sizeOf(usize)) {867pub const Verdaux = switch (@sizeOf(usize)) {
876 4 => Elf32_Verdaux,868 4 => Elf32_Verdaux,
877 8 => Elf64_Verdaux,869 8 => Elf64_Verdaux,
878 else => @compileError("expected pointer size of 32 or 64"),870 else => @compileError("expected pointer size of 32 or 64"),
std/event.zig+2-11
...@@ -76,19 +76,14 @@ pub const TcpServer = struct {...@@ -76,19 +76,14 @@ pub const TcpServer = struct {
76 }76 }
77 continue;77 continue;
78 },78 },
79 error.ConnectionAborted,79 error.ConnectionAborted, error.FileDescriptorClosed => continue,
80 error.FileDescriptorClosed => continue,
8180
82 error.PageFault => unreachable,81 error.PageFault => unreachable,
83 error.InvalidSyscall => unreachable,82 error.InvalidSyscall => unreachable,
84 error.FileDescriptorNotASocket => unreachable,83 error.FileDescriptorNotASocket => unreachable,
85 error.OperationNotSupported => unreachable,84 error.OperationNotSupported => unreachable,
8685
87 error.SystemFdQuotaExceeded,86 error.SystemFdQuotaExceeded, error.SystemResources, error.ProtocolFailure, error.BlockedByFirewall, error.Unexpected => {
88 error.SystemResources,
89 error.ProtocolFailure,
90 error.BlockedByFirewall,
91 error.Unexpected => {
92 @panic("TODO handle this error");87 @panic("TODO handle this error");
93 },88 },
94 }89 }
...@@ -121,7 +116,6 @@ pub const Loop = struct {...@@ -121,7 +116,6 @@ pub const Loop = struct {
121 pub fn removeFd(self: &Loop, fd: i32) void {116 pub fn removeFd(self: &Loop, fd: i32) void {
122 std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};117 std.os.linuxEpollCtl(self.epollfd, std.os.linux.EPOLL_CTL_DEL, fd, undefined) catch {};
123 }118 }
124
125 async fn waitFd(self: &Loop, fd: i32) !void {119 async fn waitFd(self: &Loop, fd: i32) !void {
126 defer self.removeFd(fd);120 defer self.removeFd(fd);
127 suspend |p| {121 suspend |p| {
...@@ -169,7 +163,6 @@ test "listen on a port, send bytes, receive bytes" {...@@ -169,7 +163,6 @@ test "listen on a port, send bytes, receive bytes" {
169 tcp_server: TcpServer,163 tcp_server: TcpServer,
170164
171 const Self = this;165 const Self = this;
172
173 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {166 async<&mem.Allocator> fn handler(tcp_server: &TcpServer, _addr: &const std.net.Address, _socket: &const std.os.File) void {
174 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);167 const self = @fieldParentPtr(Self, "tcp_server", tcp_server);
175 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733168 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
...@@ -184,7 +177,6 @@ test "listen on a port, send bytes, receive bytes" {...@@ -184,7 +177,6 @@ test "listen on a port, send bytes, receive bytes" {
184 cancel p;177 cancel p;
185 }178 }
186 }179 }
187
188 async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {180 async fn errorableHandler(self: &Self, _addr: &const std.net.Address, _socket: &const std.os.File) !void {
189 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733181 const addr = _addr.*; // TODO https://github.com/ziglang/zig/issues/733
190 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733182 var socket = _socket.*; // TODO https://github.com/ziglang/zig/issues/733
...@@ -207,7 +199,6 @@ test "listen on a port, send bytes, receive bytes" {...@@ -207,7 +199,6 @@ test "listen on a port, send bytes, receive bytes" {
207 defer cancel p;199 defer cancel p;
208 loop.run();200 loop.run();
209}201}
210
211async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void {202async fn doAsyncTest(loop: &Loop, address: &const std.net.Address) void {
212 errdefer @panic("test failure");203 errdefer @panic("test failure");
213204
std/fmt/errol/enum3.zig+3-4
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1pub const enum3 = []u64 {1pub const enum3 = []u64{
2 0x4e2e2785c3a2a20b,2 0x4e2e2785c3a2a20b,
3 0x240a28877a09a4e1,3 0x240a28877a09a4e1,
4 0x728fca36c06cf106,4 0x728fca36c06cf106,
...@@ -439,13 +439,13 @@ const Slab = struct {...@@ -439,13 +439,13 @@ const Slab = struct {
439};439};
440440
441fn slab(str: []const u8, exp: i32) Slab {441fn slab(str: []const u8, exp: i32) Slab {
442 return Slab {442 return Slab{
443 .str = str,443 .str = str,
444 .exp = exp,444 .exp = exp,
445 };445 };
446}446}
447447
448pub const enum3_data = []Slab {448pub const enum3_data = []Slab{
449 slab("40648030339495312", 69),449 slab("40648030339495312", 69),
450 slab("4498645355592131", -134),450 slab("4498645355592131", -134),
451 slab("678321594594593", 244),451 slab("678321594594593", 244),
...@@ -879,4 +879,3 @@ pub const enum3_data = []Slab {...@@ -879,4 +879,3 @@ pub const enum3_data = []Slab {
879 slab("32216657306260762", 218),879 slab("32216657306260762", 218),
880 slab("30423431424080128", 219),880 slab("30423431424080128", 219),
881};881};
882
std/mem.zig+8
...@@ -177,6 +177,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {...@@ -177,6 +177,14 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
177 return true;177 return true;
178}178}
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
180/// Copies ::m to newly allocated memory. Caller is responsible to free it.188/// Copies ::m to newly allocated memory. Caller is responsible to free it.
181pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T {189pub fn dupe(allocator: &Allocator, comptime T: type, m: []const T) ![]T {
182 const new_buf = try allocator.alloc(T, m.len);190 const new_buf = try allocator.alloc(T, m.len);
std/zig/ast.zig+17-9
...@@ -68,6 +68,14 @@ pub const Tree = struct {...@@ -68,6 +68,14 @@ pub const Tree = struct {
68 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));68 return self.tokenLocationPtr(start_index, self.tokens.at(token_index));
69 }69 }
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
71 pub fn dump(self: &Tree) void {79 pub fn dump(self: &Tree) void {
72 self.root_node.base.dump(0);80 self.root_node.base.dump(0);
73 }81 }
...@@ -1529,14 +1537,14 @@ pub const Node = struct {...@@ -1529,14 +1537,14 @@ pub const Node = struct {
15291537
1530 switch (self.op) {1538 switch (self.op) {
1531 Op.SliceType => |addr_of_info| {1539 Op.SliceType => |addr_of_info| {
1532 if (addr_of_info.align_expr) |align_expr| {1540 if (addr_of_info.align_info) |align_info| {
1533 if (i < 1) return align_expr;1541 if (i < 1) return align_info.node;
1534 i -= 1;1542 i -= 1;
1535 }1543 }
1536 },1544 },
1537 Op.AddrOf => |addr_of_info| {1545 Op.AddrOf => |addr_of_info| {
1538 if (addr_of_info.align_expr) |align_expr| {1546 if (addr_of_info.align_info) |align_info| {
1539 if (i < 1) return align_expr;1547 if (i < 1) return align_info.node;
1540 i -= 1;1548 i -= 1;
1541 }1549 }
1542 },1550 },
...@@ -1553,7 +1561,9 @@ pub const Node = struct {...@@ -1553,7 +1561,9 @@ pub const Node = struct {
1553 Op.NegationWrap,1561 Op.NegationWrap,
1554 Op.Try,1562 Op.Try,
1555 Op.Resume,1563 Op.Resume,
1556 Op.UnwrapMaybe => {},1564 Op.UnwrapMaybe,
1565 Op.PointerType,
1566 => {},
1557 }1567 }
15581568
1559 if (i < 1) return self.rhs;1569 if (i < 1) return self.rhs;
...@@ -1656,6 +1666,7 @@ pub const Node = struct {...@@ -1656,6 +1666,7 @@ pub const Node = struct {
1656 if (i < fields.len) return fields.at(i).*;1666 if (i < fields.len) return fields.at(i).*;
1657 i -= fields.len;1667 i -= fields.len;
1658 },1668 },
1669 Op.Deref => {},
1659 }1670 }
16601671
1661 return null;1672 return null;
...@@ -2071,7 +2082,7 @@ pub const Node = struct {...@@ -2071,7 +2082,7 @@ pub const Node = struct {
20712082
2072 const OutputList = SegmentedList(&AsmOutput, 2);2083 const OutputList = SegmentedList(&AsmOutput, 2);
2073 const InputList = SegmentedList(&AsmInput, 2);2084 const InputList = SegmentedList(&AsmInput, 2);
2074 const ClobberList = SegmentedList(&Node, 2);2085 const ClobberList = SegmentedList(TokenIndex, 2);
20752086
2076 pub fn iterate(self: &Asm, index: usize) ?&Node {2087 pub fn iterate(self: &Asm, index: usize) ?&Node {
2077 var i = index;2088 var i = index;
...@@ -2082,9 +2093,6 @@ pub const Node = struct {...@@ -2082,9 +2093,6 @@ pub const Node = struct {
2082 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;2093 if (i < self.inputs.len) return &(self.inputs.at(index).*).base;
2083 i -= self.inputs.len;2094 i -= self.inputs.len;
20842095
2085 if (i < self.clobbers.len) return self.clobbers.at(index).*;
2086 i -= self.clobbers.len;
2087
2088 return null;2096 return null;
2089 }2097 }
20902098
std/zig/parse.zig+5-3
...@@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1153,9 +1153,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1153 continue;1153 continue;
1154 },1154 },
1155 State.AsmClobberItems => |items| {1155 State.AsmClobberItems => |items| {
1156 stack.append(State{ .AsmClobberItems = items }) catch unreachable;1156 while (eatToken(&tok_it, &tree, Token.Id.StringLiteral)) |strlit| {
1157 try stack.append(State{ .IfToken = Token.Id.Comma });1157 try items.push(strlit);
1158 try stack.append(State{ .StringLiteral = OptionalCtx{ .Required = try items.addOne() } });1158 if (eatToken(&tok_it, &tree, Token.Id.Comma) == null)
1159 break;
1160 }
1159 continue;1161 continue;
1160 },1162 },
11611163
std/zig/parser_test.zig+433-24
...@@ -1,10 +1,427 @@...@@ -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
1test "zig fmt: switch cases trailing comma" {418test "zig fmt: switch cases trailing comma" {
2 try testTransform(419 try testTransform(
3 \\fn switch_cases(x: i32) void {420 \\fn switch_cases(x: i32) void {
4 \\ switch (x) {421 \\ switch (x) {
5 \\ 1,2,3 => {},422 \\ 1,2,3 => {},
6 \\ 4,5, => {},423 \\ 4,5, => {},
7 \\ 6...8, => {},424 \\ 6... 8, => {},
8 \\ else => {},425 \\ else => {},
9 \\ }426 \\ }
10 \\}427 \\}
...@@ -13,8 +430,9 @@ test "zig fmt: switch cases trailing comma" {...@@ -13,8 +430,9 @@ test "zig fmt: switch cases trailing comma" {
13 \\ switch (x) {430 \\ switch (x) {
14 \\ 1, 2, 3 => {},431 \\ 1, 2, 3 => {},
15 \\ 4,432 \\ 4,
16 \\ 5, => {},433 \\ 5,
17 \\ 6 ... 8 => {},434 \\ => {},
435 \\ 6...8 => {},
18 \\ else => {},436 \\ else => {},
19 \\ }437 \\ }
20 \\}438 \\}
...@@ -36,16 +454,20 @@ test "zig fmt: add trailing comma to array literal" {...@@ -36,16 +454,20 @@ test "zig fmt: add trailing comma to array literal" {
36 \\comptime {454 \\comptime {
37 \\ return []u16{'m', 's', 'y', 's', '-' // hi455 \\ return []u16{'m', 's', 'y', 's', '-' // hi
38 \\ };456 \\ };
457 \\ return []u16{'m', 's', 'y', 's',
458 \\ '-'};
459 \\ return []u16{'m', 's', 'y', 's', '-'};
39 \\}460 \\}
40 ,461 ,
41 \\comptime {462 \\comptime {
42 \\ return []u16{463 \\ return []u16{
43 \\ 'm',464 \\ 'm', 's', 'y', 's', '-', // hi
44 \\ 's',
45 \\ 'y',
46 \\ 's',
47 \\ '-', // hi
48 \\ };465 \\ };
466 \\ return []u16{
467 \\ 'm', 's', 'y', 's',
468 \\ '-',
469 \\ };
470 \\ return []u16{ 'm', 's', 'y', 's', '-' };
49 \\}471 \\}
50 \\472 \\
51 );473 );
...@@ -252,20 +674,6 @@ test "zig fmt: add comma on last switch prong" {...@@ -252,20 +674,6 @@ test "zig fmt: add comma on last switch prong" {
252 );674 );
253}675}
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
269test "zig fmt: same-line comment after a statement" {677test "zig fmt: same-line comment after a statement" {
270 try testCanonical(678 try testCanonical(
271 \\test "" {679 \\test "" {
...@@ -1026,7 +1434,7 @@ test "zig fmt: switch" {...@@ -1026,7 +1434,7 @@ test "zig fmt: switch" {
1026 \\ 0 => {},1434 \\ 0 => {},
1027 \\ 1 => unreachable,1435 \\ 1 => unreachable,
1028 \\ 2, 3 => {},1436 \\ 2, 3 => {},
1029 \\ 4 ... 7 => {},1437 \\ 4...7 => {},
1030 \\ 1 + 4 * 3 + 22 => {},1438 \\ 1 + 4 * 3 + 22 => {},
1031 \\ else => {1439 \\ else => {
1032 \\ const a = 1;1440 \\ const a = 1;
...@@ -1286,7 +1694,8 @@ test "zig fmt: inline asm" {...@@ -1286,7 +1694,8 @@ test "zig fmt: inline asm" {
1286 \\ : [ret] "={rax}" (-> usize)1694 \\ : [ret] "={rax}" (-> usize)
1287 \\ : [number] "{rax}" (number),1695 \\ : [number] "{rax}" (number),
1288 \\ [arg1] "{rdi}" (arg1)1696 \\ [arg1] "{rdi}" (arg1)
1289 \\ : "rcx", "r11");1697 \\ : "rcx", "r11"
1698 \\ );
1290 \\}1699 \\}
1291 \\1700 \\
1292 );1701 );
std/zig/render.zig+889-535
...@@ -19,7 +19,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(...@@ -19,7 +19,7 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
19 var tok_it = tree.tokens.iterator(0);19 var tok_it = tree.tokens.iterator(0);
20 while (tok_it.next()) |token| {20 while (tok_it.next()) |token| {
21 if (token.id != Token.Id.LineComment) break;21 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), " "));
23 if (tok_it.peek()) |next_token| {23 if (tok_it.peek()) |next_token| {
24 const loc = tree.tokenLocationPtr(token.end, next_token);24 const loc = tree.tokenLocationPtr(token.end, next_token);
25 if (loc.line >= 2) {25 if (loc.line >= 2) {
...@@ -28,41 +28,43 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(...@@ -28,41 +28,43 @@ pub fn render(allocator: &mem.Allocator, stream: var, tree: &ast.Tree) (@typeOf(
28 }28 }
29 }29 }
3030
3131 var start_col: usize = 0;
32 var it = tree.root_node.decls.iterator(0);32 var it = tree.root_node.decls.iterator(0);
33 while (it.next()) |decl| {33 while (it.next()) |decl| {
34 try renderTopLevelDecl(allocator, stream, tree, 0, decl.*);34 try renderTopLevelDecl(allocator, stream, tree, 0, &start_col, decl.*);
35 if (it.peek()) |next_decl| {35 if (it.peek()) |next_decl| {
36 try renderExtraNewline(tree, stream, next_decl.*);36 try renderExtraNewline(tree, stream, &start_col, next_decl.*);
37 }37 }
38 }38 }
39}39}
4040
41fn renderExtraNewline(tree: &ast.Tree, stream: var, node: &ast.Node) !void {41fn renderExtraNewline(tree: &ast.Tree, stream: var, start_col: &usize, node: &ast.Node) !void {
42 var first_token = node.firstToken();42 const first_token = node.firstToken();
43 while (tree.tokens.at(first_token - 1).id == Token.Id.DocComment) {43 var prev_token = first_token;
44 first_token -= 1;44 while (tree.tokens.at(prev_token - 1).id == Token.Id.DocComment) {
45 prev_token -= 1;
45 }46 }
46 const prev_token_end = tree.tokens.at(first_token - 1).end;47 const prev_token_end = tree.tokens.at(prev_token - 1).end;
47 const loc = tree.tokenLocation(prev_token_end, first_token);48 const loc = tree.tokenLocation(prev_token_end, first_token);
48 if (loc.line >= 2) {49 if (loc.line >= 2) {
49 try stream.writeByte('\n');50 try stream.writeByte('\n');
51 start_col.* = 0;
50 }52 }
51}53}
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 {
54 switch (decl.id) {56 switch (decl.id) {
55 ast.Node.Id.FnProto => {57 ast.Node.Id.FnProto => {
56 const fn_proto = @fieldParentPtr(ast.Node.FnProto, "base", decl);58 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
60 if (fn_proto.body_node) |body_node| {62 if (fn_proto.body_node) |body_node| {
61 try renderExpression(allocator, stream, tree, indent, decl, Space.Space);63 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.Space);
62 try renderExpression(allocator, stream, tree, indent, body_node, Space.Newline);64 try renderExpression(allocator, stream, tree, indent, start_col, body_node, Space.Newline);
63 } else {65 } else {
64 try renderExpression(allocator, stream, tree, indent, decl, Space.None);66 try renderExpression(allocator, stream, tree, indent, start_col, decl, Space.None);
65 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, Space.Newline);67 try renderToken(tree, stream, tree.nextToken(decl.lastToken()), indent, start_col, Space.Newline);
66 }68 }
67 },69 },
6870
...@@ -70,148 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i...@@ -70,148 +72,154 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i
70 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);72 const use_decl = @fieldParentPtr(ast.Node.Use, "base", decl);
7173
72 if (use_decl.visib_token) |visib_token| {74 if (use_decl.visib_token) |visib_token| {
73 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub75 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
74 }76 }
75 try renderToken(tree, stream, use_decl.use_token, indent, Space.Space); // use77 try renderToken(tree, stream, use_decl.use_token, indent, start_col, Space.Space); // use
76 try renderExpression(allocator, stream, tree, indent, use_decl.expr, Space.None);78 try renderExpression(allocator, stream, tree, indent, start_col, use_decl.expr, Space.None);
77 try renderToken(tree, stream, use_decl.semicolon_token, indent, Space.Newline); // ;79 try renderToken(tree, stream, use_decl.semicolon_token, indent, start_col, Space.Newline); // ;
78 },80 },
7981
80 ast.Node.Id.VarDecl => {82 ast.Node.Id.VarDecl => {
81 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);83 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", decl);
8284
83 try renderDocComments(tree, stream, var_decl, indent);85 try renderDocComments(tree, stream, var_decl, indent, start_col);
84 try renderVarDecl(allocator, stream, tree, indent, var_decl);86 try renderVarDecl(allocator, stream, tree, indent, start_col, var_decl);
85 },87 },
8688
87 ast.Node.Id.TestDecl => {89 ast.Node.Id.TestDecl => {
88 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);90 const test_decl = @fieldParentPtr(ast.Node.TestDecl, "base", decl);
8991
90 try renderDocComments(tree, stream, test_decl, indent);92 try renderDocComments(tree, stream, test_decl, indent, start_col);
91 try renderToken(tree, stream, test_decl.test_token, indent, Space.Space);93 try renderToken(tree, stream, test_decl.test_token, indent, start_col, Space.Space);
92 try renderExpression(allocator, stream, tree, indent, test_decl.name, Space.Space);94 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.name, Space.Space);
93 try renderExpression(allocator, stream, tree, indent, test_decl.body_node, Space.Newline);95 try renderExpression(allocator, stream, tree, indent, start_col, test_decl.body_node, Space.Newline);
94 },96 },
9597
96 ast.Node.Id.StructField => {98 ast.Node.Id.StructField => {
97 const field = @fieldParentPtr(ast.Node.StructField, "base", decl);99 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);
100 if (field.visib_token) |visib_token| {102 if (field.visib_token) |visib_token| {
101 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub103 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
102 }104 }
103 try renderToken(tree, stream, field.name_token, indent, Space.None); // name105 try renderToken(tree, stream, field.name_token, indent, start_col, Space.None); // name
104 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, Space.Space); // :106 try renderToken(tree, stream, tree.nextToken(field.name_token), indent, start_col, Space.Space); // :
105 try renderExpression(allocator, stream, tree, indent, field.type_expr, Space.None); // type107 try renderExpression(allocator, stream, tree, indent, start_col, field.type_expr, Space.Comma); // type,
106 try renderToken(tree, stream, tree.nextToken(field.lastToken()), indent, Space.Newline); // ,
107 },108 },
108109
109 ast.Node.Id.UnionTag => {110 ast.Node.Id.UnionTag => {
110 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);111 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
111112
112 try renderDocComments(tree, stream, tag, indent);113 try renderDocComments(tree, stream, tag, indent, start_col);
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
116114
117 if (tag.type_expr) |type_expr| {115 if (tag.type_expr == null and tag.value_expr == null) {
118 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // :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;119 if (tag.type_expr == null) {
121 try renderExpression(allocator, stream, tree, indent, type_expr, after_type_space);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
122 }123 }
123124
124 if (tag.value_expr) |value_expr| {125 if (tag.type_expr) |type_expr| {
125 try renderToken(tree, stream, tree.prevToken(value_expr.firstToken()), indent, Space.Space); // =126 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, start_col, Space.Space); // :
126 try renderExpression(allocator, stream, tree, indent, value_expr, Space.None);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 }
127 }134 }
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,
130 },139 },
131140
132 ast.Node.Id.EnumTag => {141 ast.Node.Id.EnumTag => {
133 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);142 const tag = @fieldParentPtr(ast.Node.EnumTag, "base", decl);
134143
135 try renderDocComments(tree, stream, tag, indent);144 try renderDocComments(tree, stream, tag, indent, start_col);
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
139145
140 if (tag.value) |value| {146 if (tag.value) |value| {
141 try renderToken(tree, stream, tree.nextToken(tag.name_token), indent, Space.Space); // =147 try renderToken(tree, stream, tag.name_token, indent, start_col, Space.Space); // name
142 try renderExpression(allocator, stream, tree, indent, value, Space.None);
143 }
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 }
146 },154 },
147155
148 ast.Node.Id.Comptime => {156 ast.Node.Id.Comptime => {
149 assert(!decl.requireSemiColon());157 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);
151 },159 },
152 else => unreachable,160 else => unreachable,
153 }161 }
154}162}
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 {
157 switch (base.id) {165 switch (base.id) {
158 ast.Node.Id.Identifier => {166 ast.Node.Id.Identifier => {
159 const identifier = @fieldParentPtr(ast.Node.Identifier, "base", base);167 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);
161 },169 },
162 ast.Node.Id.Block => {170 ast.Node.Id.Block => {
163 const block = @fieldParentPtr(ast.Node.Block, "base", base);171 const block = @fieldParentPtr(ast.Node.Block, "base", base);
164172
165 if (block.label) |label| {173 if (block.label) |label| {
166 try renderToken(tree, stream, label, indent, Space.None);174 try renderToken(tree, stream, label, indent, start_col, Space.None);
167 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);175 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
168 }176 }
169177
170 if (block.statements.len == 0) {178 if (block.statements.len == 0) {
171 try renderToken(tree, stream, block.lbrace, indent + indent_delta, Space.None);179 try renderToken(tree, stream, block.lbrace, indent + indent_delta, start_col, Space.None);
172 try renderToken(tree, stream, block.rbrace, indent, space);180 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
173 } else {181 } else {
174 const block_indent = indent + indent_delta;182 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
177 var it = block.statements.iterator(0);185 var it = block.statements.iterator(0);
178 while (it.next()) |statement| {186 while (it.next()) |statement| {
179 try stream.writeByteNTimes(' ', block_indent);187 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
182 if (it.peek()) |next_statement| {190 if (it.peek()) |next_statement| {
183 try renderExtraNewline(tree, stream, next_statement.*);191 try renderExtraNewline(tree, stream, start_col, next_statement.*);
184 }192 }
185 }193 }
186194
187 try stream.writeByteNTimes(' ', indent);195 try stream.writeByteNTimes(' ', indent);
188 try renderToken(tree, stream, block.rbrace, indent, space);196 return renderToken(tree, stream, block.rbrace, indent, start_col, space);
189 }197 }
190 },198 },
191 ast.Node.Id.Defer => {199 ast.Node.Id.Defer => {
192 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);200 const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
193201
194 try renderToken(tree, stream, defer_node.defer_token, indent, Space.Space);202 try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
195 try renderExpression(allocator, stream, tree, indent, defer_node.expr, space);203 return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
196 },204 },
197 ast.Node.Id.Comptime => {205 ast.Node.Id.Comptime => {
198 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);206 const comptime_node = @fieldParentPtr(ast.Node.Comptime, "base", base);
199207
200 try renderToken(tree, stream, comptime_node.comptime_token, indent, Space.Space);208 try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space);
201 try renderExpression(allocator, stream, tree, indent, comptime_node.expr, space);209 return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space);
202 },210 },
203211
204 ast.Node.Id.AsyncAttribute => {212 ast.Node.Id.AsyncAttribute => {
205 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);213 const async_attr = @fieldParentPtr(ast.Node.AsyncAttribute, "base", base);
206214
207 if (async_attr.allocator_type) |allocator_type| {215 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);218 try renderToken(tree, stream, tree.nextToken(async_attr.async_token), indent, start_col, Space.None);
211 try renderExpression(allocator, stream, tree, indent, allocator_type, Space.None);219 try renderExpression(allocator, stream, tree, indent, start_col, allocator_type, Space.None);
212 try renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, space);220 return renderToken(tree, stream, tree.nextToken(allocator_type.lastToken()), indent, start_col, space);
213 } else {221 } 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);
215 }223 }
216 },224 },
217225
...@@ -219,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -219,24 +227,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
219 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);227 const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
220228
221 if (suspend_node.label) |label| {229 if (suspend_node.label) |label| {
222 try renderToken(tree, stream, label, indent, Space.None);230 try renderToken(tree, stream, label, indent, start_col, Space.None);
223 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space);231 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
224 }232 }
225233
226 if (suspend_node.payload) |payload| {234 if (suspend_node.payload) |payload| {
227 if (suspend_node.body) |body| {235 if (suspend_node.body) |body| {
228 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);236 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
229 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);237 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
230 try renderExpression(allocator, stream, tree, indent, body, space);238 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
231 } else {239 } else {
232 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);240 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
233 try renderExpression(allocator, stream, tree, indent, payload, space);241 return renderExpression(allocator, stream, tree, indent, start_col, payload, space);
234 }242 }
235 } else if (suspend_node.body) |body| {243 } else if (suspend_node.body) |body| {
236 try renderToken(tree, stream, suspend_node.suspend_token, indent, Space.Space);244 try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
237 try renderExpression(allocator, stream, tree, indent, body, space);245 return renderExpression(allocator, stream, tree, indent, start_col, body, space);
238 } else {246 } 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);
240 }248 }
241 },249 },
242250
...@@ -245,20 +253,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -245,20 +253,31 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
245253
246 const op_token = tree.tokens.at(infix_op_node.op_token);254 const op_token = tree.tokens.at(infix_op_node.op_token);
247 const op_space = switch (infix_op_node.op) {255 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,
249 else => Space.Space,257 else => Space.Space,
250 };258 };
251 try renderExpression(allocator, stream, tree, indent, infix_op_node.lhs, op_space);259 try renderExpression(allocator, stream, tree, indent, start_col, infix_op_node.lhs, op_space);
252 try renderToken(tree, stream, infix_op_node.op_token, indent, 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
254 switch (infix_op_node.op) {273 switch (infix_op_node.op) {
255 ast.Node.InfixOp.Op.Catch => |maybe_payload| if (maybe_payload) |payload| {274 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);
257 },276 },
258 else => {},277 else => {},
259 }278 }
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);
262 },281 },
263282
264 ast.Node.Id.PrefixOp => {283 ast.Node.Id.PrefixOp => {
...@@ -266,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -266,81 +285,81 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
266285
267 switch (prefix_op_node.op) {286 switch (prefix_op_node.op) {
268 ast.Node.PrefixOp.Op.AddrOf => |addr_of_info| {287 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); // &
270 if (addr_of_info.align_info) |align_info| {289 if (addr_of_info.align_info) |align_info| {
271 const lparen_token = tree.prevToken(align_info.node.firstToken());290 const lparen_token = tree.prevToken(align_info.node.firstToken());
272 const align_token = tree.prevToken(lparen_token);291 const align_token = tree.prevToken(lparen_token);
273292
274 try renderToken(tree, stream, align_token, indent, Space.None); // align293 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
275 try renderToken(tree, stream, lparen_token, indent, Space.None); // (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
279 if (align_info.bit_range) |bit_range| {298 if (align_info.bit_range) |bit_range| {
280 const colon1 = tree.prevToken(bit_range.start.firstToken());299 const colon1 = tree.prevToken(bit_range.start.firstToken());
281 const colon2 = tree.prevToken(bit_range.end.firstToken());300 const colon2 = tree.prevToken(bit_range.end.firstToken());
282301
283 try renderToken(tree, stream, colon1, indent, Space.None); // :302 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
284 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);303 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
285 try renderToken(tree, stream, colon2, indent, Space.None); // :304 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
286 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);305 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
287306
288 const rparen_token = tree.nextToken(bit_range.end.lastToken());307 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); // )
290 } else {309 } else {
291 const rparen_token = tree.nextToken(align_info.node.lastToken());310 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); // )
293 }312 }
294 }313 }
295 if (addr_of_info.const_token) |const_token| {314 if (addr_of_info.const_token) |const_token| {
296 try renderToken(tree, stream, const_token, indent, Space.Space); // const315 try renderToken(tree, stream, const_token, indent, start_col, Space.Space); // const
297 }316 }
298 if (addr_of_info.volatile_token) |volatile_token| {317 if (addr_of_info.volatile_token) |volatile_token| {
299 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile318 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
300 }319 }
301 },320 },
302321
303 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {322 ast.Node.PrefixOp.Op.SliceType => |addr_of_info| {
304 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [323 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
305 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, Space.None); // ]324 try renderToken(tree, stream, tree.nextToken(prefix_op_node.op_token), indent, start_col, Space.None); // ]
306325
307 if (addr_of_info.align_info) |align_info| {326 if (addr_of_info.align_info) |align_info| {
308 const lparen_token = tree.prevToken(align_info.node.firstToken());327 const lparen_token = tree.prevToken(align_info.node.firstToken());
309 const align_token = tree.prevToken(lparen_token);328 const align_token = tree.prevToken(lparen_token);
310329
311 try renderToken(tree, stream, align_token, indent, Space.None); // align330 try renderToken(tree, stream, align_token, indent, start_col, Space.None); // align
312 try renderToken(tree, stream, lparen_token, indent, Space.None); // (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
316 if (align_info.bit_range) |bit_range| {335 if (align_info.bit_range) |bit_range| {
317 const colon1 = tree.prevToken(bit_range.start.firstToken());336 const colon1 = tree.prevToken(bit_range.start.firstToken());
318 const colon2 = tree.prevToken(bit_range.end.firstToken());337 const colon2 = tree.prevToken(bit_range.end.firstToken());
319338
320 try renderToken(tree, stream, colon1, indent, Space.None); // :339 try renderToken(tree, stream, colon1, indent, start_col, Space.None); // :
321 try renderExpression(allocator, stream, tree, indent, bit_range.start, Space.None);340 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.start, Space.None);
322 try renderToken(tree, stream, colon2, indent, Space.None); // :341 try renderToken(tree, stream, colon2, indent, start_col, Space.None); // :
323 try renderExpression(allocator, stream, tree, indent, bit_range.end, Space.None);342 try renderExpression(allocator, stream, tree, indent, start_col, bit_range.end, Space.None);
324343
325 const rparen_token = tree.nextToken(bit_range.end.lastToken());344 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); // )
327 } else {346 } else {
328 const rparen_token = tree.nextToken(align_info.node.lastToken());347 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); // )
330 }349 }
331 }350 }
332 if (addr_of_info.const_token) |const_token| {351 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);
334 }353 }
335 if (addr_of_info.volatile_token) |volatile_token| {354 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);
337 }356 }
338 },357 },
339358
340 ast.Node.PrefixOp.Op.ArrayType => |array_index| {359 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
341 try renderToken(tree, stream, prefix_op_node.op_token, indent, Space.None); // [360 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [
342 try renderExpression(allocator, stream, tree, indent, array_index, Space.None);361 try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None);
343 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, Space.None); // ]362 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ]
344 },363 },
345 ast.Node.PrefixOp.Op.BitNot,364 ast.Node.PrefixOp.Op.BitNot,
346 ast.Node.PrefixOp.Op.BoolNot,365 ast.Node.PrefixOp.Op.BoolNot,
...@@ -349,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -349,18 +368,18 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
349 ast.Node.PrefixOp.Op.UnwrapMaybe,368 ast.Node.PrefixOp.Op.UnwrapMaybe,
350 ast.Node.PrefixOp.Op.MaybeType,369 ast.Node.PrefixOp.Op.MaybeType,
351 ast.Node.PrefixOp.Op.PointerType => {370 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);
353 },372 },
354373
355 ast.Node.PrefixOp.Op.Try,374 ast.Node.PrefixOp.Op.Try,
356 ast.Node.PrefixOp.Op.Await,375 ast.Node.PrefixOp.Op.Await,
357 ast.Node.PrefixOp.Op.Cancel,376 ast.Node.PrefixOp.Op.Cancel,
358 ast.Node.PrefixOp.Op.Resume => {377 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);
360 },379 },
361 }380 }
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);
364 },383 },
365384
366 ast.Node.Id.SuffixOp => {385 ast.Node.Id.SuffixOp => {
...@@ -369,80 +388,152 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -369,80 +388,152 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
369 switch (suffix_op.op) {388 switch (suffix_op.op) {
370 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {389 @TagType(ast.Node.SuffixOp.Op).Call => |*call_info| {
371 if (call_info.async_attr) |async_attr| {390 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);
373 }392 }
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
377 const lparen = tree.nextToken(suffix_op.lhs.lastToken());396 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
380 var it = call_info.params.iterator(0);438 var it = call_info.params.iterator(0);
381 while (it.next()) |param_node| {439 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
384 if (it.peek() != null) {442 if (it.peek() != null) {
385 const comma = tree.nextToken(param_node.*.lastToken());443 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);
387 }445 }
388 }446 }
389447 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
390 try renderToken(tree, stream, suffix_op.rtoken, indent, space);
391 },448 },
392449
393 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {450 ast.Node.SuffixOp.Op.ArrayAccess => |index_expr| {
394 const lbracket = tree.prevToken(index_expr.firstToken());451 const lbracket = tree.prevToken(index_expr.firstToken());
395 const rbracket = tree.nextToken(index_expr.lastToken());452 const rbracket = tree.nextToken(index_expr.lastToken());
396453
397 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);454 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
398 try renderToken(tree, stream, lbracket, indent, Space.None); // [455 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
399 try renderExpression(allocator, stream, tree, indent, index_expr, Space.None);456 try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None);
400 try renderToken(tree, stream, rbracket, indent, space); // ]457 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
401 },458 },
402459
403 ast.Node.SuffixOp.Op.Deref => {460 ast.Node.SuffixOp.Op.Deref => {
404 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);461 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
405 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, Space.None); // .462 try renderToken(tree, stream, tree.prevToken(suffix_op.rtoken), indent, start_col, Space.None); // .
406 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // *463 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // *
407 },464 },
408465
409 @TagType(ast.Node.SuffixOp.Op).Slice => |range| {466 @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
412 const lbracket = tree.prevToken(range.start.firstToken());469 const lbracket = tree.prevToken(range.start.firstToken());
413 const dotdot = tree.nextToken(range.start.lastToken());470 const dotdot = tree.nextToken(range.start.lastToken());
414471
415 try renderToken(tree, stream, lbracket, indent, Space.None); // [472 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
416 try renderExpression(allocator, stream, tree, indent, range.start, Space.None);473 try renderExpression(allocator, stream, tree, indent, start_col, range.start, Space.None);
417 try renderToken(tree, stream, dotdot, indent, Space.None); // ..474 try renderToken(tree, stream, dotdot, indent, start_col, Space.None); // ..
418 if (range.end) |end| {475 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);
420 }477 }
421 try renderToken(tree, stream, suffix_op.rtoken, indent, space); // ]478 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space); // ]
422 },479 },
423480
424 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {481 ast.Node.SuffixOp.Op.StructInitializer => |*field_inits| {
425 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());482 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
426483
427 if (field_inits.len == 0) {484 if (field_inits.len == 0) {
428 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);485 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
429 try renderToken(tree, stream, lbrace, indent, Space.None);486 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
430 try renderToken(tree, stream, suffix_op.rtoken, indent, space);487 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
431 return;
432 }488 }
433489
434 if (field_inits.len == 1) {490 if (field_inits.len == 1) blk: {
435 const field_init = field_inits.at(0).*;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);493 if (field_init.expr.cast(ast.Node.SuffixOp)) |nested_suffix_op| {
438 try renderToken(tree, stream, lbrace, indent, Space.Space);494 if (nested_suffix_op.op == ast.Node.SuffixOp.Op.StructInitializer) {
439 try renderExpression(allocator, stream, tree, indent, field_init, Space.Space);495 break :blk;
440 try renderToken(tree, stream, suffix_op.rtoken, indent, space);496 }
441 return;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);
442 }503 }
443504
444 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);505 const src_has_trailing_comma = blk: {
445 try renderToken(tree, stream, lbrace, indent, Space.Newline);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
447 const new_indent = indent + indent_delta;538 const new_indent = indent + indent_delta;
448539
...@@ -451,63 +542,116 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -451,63 +542,116 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
451 try stream.writeByteNTimes(' ', new_indent);542 try stream.writeByteNTimes(' ', new_indent);
452543
453 if (it.peek()) |next_field_init| {544 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
456 const comma = tree.nextToken(field_init.*.lastToken());547 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.*);
460 } else {551 } 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);
462 }553 }
463 }554 }
464555
465 try stream.writeByteNTimes(' ', indent);556 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);
467 },558 },
468559
469 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {560 ast.Node.SuffixOp.Op.ArrayInitializer => |*exprs| {
470 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());561 const lbrace = tree.nextToken(suffix_op.lhs.lastToken());
471562
472 if (exprs.len == 0) {563 if (exprs.len == 0) {
473 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);564 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
474 try renderToken(tree, stream, lbrace, indent, Space.None);565 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
475 try renderToken(tree, stream, suffix_op.rtoken, indent, space);566 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
476 return;
477 }567 }
478 if (exprs.len == 1) {568 if (exprs.len == 1) {
479 const expr = exprs.at(0).*;569 const expr = exprs.at(0).*;
480570
481 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);571 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
482 try renderToken(tree, stream, lbrace, indent, Space.None);572 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
483 try renderExpression(allocator, stream, tree, indent, expr, Space.None);573 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
484 try renderToken(tree, stream, suffix_op.rtoken, indent, space);574 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
485 return;
486 }575 }
487576
488 try renderExpression(allocator, stream, tree, indent, suffix_op.lhs, Space.None);577 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
489578
490 const new_indent = indent + indent_delta;579 // scan to find row size
491 try renderToken(tree, stream, lbrace, new_indent, Space.Newline);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);610 if (maybe_row_size) |row_size| {
494 while (it.next()) |expr| {611 const new_indent = indent + indent_delta;
612 try renderToken(tree, stream, lbrace, new_indent, start_col, Space.Newline);
495 try stream.writeByteNTimes(' ', new_indent);613 try stream.writeByteNTimes(' ', new_indent);
496614
497 if (it.peek()) |next_expr| {615 var it = exprs.iterator(0);
498 try renderExpression(allocator, stream, tree, new_indent, expr.*, Space.None);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());621 const comma = tree.nextToken(expr.*.lastToken());
501 try renderToken(tree, stream, comma, new_indent, Space.Newline); // ,
502622
503 try renderExtraNewline(tree, stream, next_expr.*);623 if (i != row_size) {
504 } else {624 try renderToken(tree, stream, comma, new_indent, start_col, Space.Space); // ,
505 try renderTrailingComma(allocator, stream, tree, new_indent, expr.*, Space.Newline);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 }
506 }651 }
507 }
508652
509 try stream.writeByteNTimes(' ', indent);653 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
510 try renderToken(tree, stream, suffix_op.rtoken, indent, space);654 }
511 },655 },
512 }656 }
513 },657 },
...@@ -517,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -517,195 +661,204 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
517661
518 switch (flow_expr.kind) {662 switch (flow_expr.kind) {
519 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {663 ast.Node.ControlFlowExpression.Kind.Break => |maybe_label| {
520 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;664 if (maybe_label == null and flow_expr.rhs == null) {
521 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);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
522 if (maybe_label) |label| {669 if (maybe_label) |label| {
523 const colon = tree.nextToken(flow_expr.ltoken);670 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;673 if (flow_expr.rhs == null) {
527 try renderExpression(allocator, stream, tree, indent, label, expr_space);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
528 }677 }
529 },678 },
530 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {679 ast.Node.ControlFlowExpression.Kind.Continue => |maybe_label| {
531 const kw_space = if (maybe_label != null or flow_expr.rhs != null) Space.Space else space;680 assert(flow_expr.rhs == null);
532 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);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
533 if (maybe_label) |label| {687 if (maybe_label) |label| {
534 const colon = tree.nextToken(flow_expr.ltoken);688 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;691 return renderExpression(allocator, stream, tree, indent, start_col, label, space);
538 try renderExpression(allocator, stream, tree, indent, label, space);
539 }692 }
540 },693 },
541 ast.Node.ControlFlowExpression.Kind.Return => {694 ast.Node.ControlFlowExpression.Kind.Return => {
542 const kw_space = if (flow_expr.rhs != null) Space.Space else space;695 if (flow_expr.rhs == null) {
543 try renderToken(tree, stream, flow_expr.ltoken, indent, kw_space);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);
544 },699 },
545 }700 }
546701
547 if (flow_expr.rhs) |rhs| {702 return renderExpression(allocator, stream, tree, indent, start_col, ??flow_expr.rhs, space);
548 try renderExpression(allocator, stream, tree, indent, rhs, space);
549 }
550 },703 },
551704
552 ast.Node.Id.Payload => {705 ast.Node.Id.Payload => {
553 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);706 const payload = @fieldParentPtr(ast.Node.Payload, "base", base);
554707
555 try renderToken(tree, stream, payload.lpipe, indent, Space.None);708 try renderToken(tree, stream, payload.lpipe, indent, start_col, Space.None);
556 try renderExpression(allocator, stream, tree, indent, payload.error_symbol, Space.None);709 try renderExpression(allocator, stream, tree, indent, start_col, payload.error_symbol, Space.None);
557 try renderToken(tree, stream, payload.rpipe, indent, space);710 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
558 },711 },
559712
560 ast.Node.Id.PointerPayload => {713 ast.Node.Id.PointerPayload => {
561 const payload = @fieldParentPtr(ast.Node.PointerPayload, "base", base);714 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);
564 if (payload.ptr_token) |ptr_token| {717 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);
566 }719 }
567 try renderExpression(allocator, stream, tree, indent, payload.value_symbol, Space.None);720 try renderExpression(allocator, stream, tree, indent, start_col, payload.value_symbol, Space.None);
568 try renderToken(tree, stream, payload.rpipe, indent, space);721 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
569 },722 },
570723
571 ast.Node.Id.PointerIndexPayload => {724 ast.Node.Id.PointerIndexPayload => {
572 const payload = @fieldParentPtr(ast.Node.PointerIndexPayload, "base", base);725 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);
575 if (payload.ptr_token) |ptr_token| {728 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);
577 }730 }
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
580 if (payload.index_symbol) |index_symbol| {733 if (payload.index_symbol) |index_symbol| {
581 const comma = tree.nextToken(payload.value_symbol.lastToken());734 const comma = tree.nextToken(payload.value_symbol.lastToken());
582735
583 try renderToken(tree, stream, comma, indent, Space.Space);736 try renderToken(tree, stream, comma, indent, start_col, Space.Space);
584 try renderExpression(allocator, stream, tree, indent, index_symbol, Space.None);737 try renderExpression(allocator, stream, tree, indent, start_col, index_symbol, Space.None);
585 }738 }
586739
587 try renderToken(tree, stream, payload.rpipe, indent, space);740 return renderToken(tree, stream, payload.rpipe, indent, start_col, space);
588 },741 },
589742
590 ast.Node.Id.GroupedExpression => {743 ast.Node.Id.GroupedExpression => {
591 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);744 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
592745
593 try renderToken(tree, stream, grouped_expr.lparen, indent, Space.None);746 try renderToken(tree, stream, grouped_expr.lparen, indent, start_col, Space.None);
594 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr, Space.None);747 try renderExpression(allocator, stream, tree, indent, start_col, grouped_expr.expr, Space.None);
595 try renderToken(tree, stream, grouped_expr.rparen, indent, space);748 return renderToken(tree, stream, grouped_expr.rparen, indent, start_col, space);
596 },749 },
597750
598 ast.Node.Id.FieldInitializer => {751 ast.Node.Id.FieldInitializer => {
599 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);752 const field_init = @fieldParentPtr(ast.Node.FieldInitializer, "base", base);
600753
601 try renderToken(tree, stream, field_init.period_token, indent, Space.None); // .754 try renderToken(tree, stream, field_init.period_token, indent, start_col, Space.None); // .
602 try renderToken(tree, stream, field_init.name_token, indent, Space.Space); // name755 try renderToken(tree, stream, field_init.name_token, indent, start_col, Space.Space); // name
603 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, Space.Space); // =756 try renderToken(tree, stream, tree.nextToken(field_init.name_token), indent, start_col, Space.Space); // =
604 try renderExpression(allocator, stream, tree, indent, field_init.expr, space);757 return renderExpression(allocator, stream, tree, indent, start_col, field_init.expr, space);
605 },758 },
606759
607 ast.Node.Id.IntegerLiteral => {760 ast.Node.Id.IntegerLiteral => {
608 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);761 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);
610 },763 },
611 ast.Node.Id.FloatLiteral => {764 ast.Node.Id.FloatLiteral => {
612 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);765 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);
614 },767 },
615 ast.Node.Id.StringLiteral => {768 ast.Node.Id.StringLiteral => {
616 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);769 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);
618 },771 },
619 ast.Node.Id.CharLiteral => {772 ast.Node.Id.CharLiteral => {
620 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);773 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);
622 },775 },
623 ast.Node.Id.BoolLiteral => {776 ast.Node.Id.BoolLiteral => {
624 const bool_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);777 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);
626 },779 },
627 ast.Node.Id.NullLiteral => {780 ast.Node.Id.NullLiteral => {
628 const null_literal = @fieldParentPtr(ast.Node.NullLiteral, "base", base);781 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);
630 },783 },
631 ast.Node.Id.ThisLiteral => {784 ast.Node.Id.ThisLiteral => {
632 const this_literal = @fieldParentPtr(ast.Node.ThisLiteral, "base", base);785 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);
634 },787 },
635 ast.Node.Id.Unreachable => {788 ast.Node.Id.Unreachable => {
636 const unreachable_node = @fieldParentPtr(ast.Node.Unreachable, "base", base);789 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);
638 },791 },
639 ast.Node.Id.ErrorType => {792 ast.Node.Id.ErrorType => {
640 const error_type = @fieldParentPtr(ast.Node.ErrorType, "base", base);793 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);
642 },795 },
643 ast.Node.Id.VarType => {796 ast.Node.Id.VarType => {
644 const var_type = @fieldParentPtr(ast.Node.VarType, "base", base);797 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);
646 },799 },
647 ast.Node.Id.ContainerDecl => {800 ast.Node.Id.ContainerDecl => {
648 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);801 const container_decl = @fieldParentPtr(ast.Node.ContainerDecl, "base", base);
649802
650 if (container_decl.layout_token) |layout_token| {803 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);
652 }805 }
653806
654 switch (container_decl.init_arg_expr) {807 switch (container_decl.init_arg_expr) {
655 ast.Node.ContainerDecl.InitArg.None => {808 ast.Node.ContainerDecl.InitArg.None => {
656 try renderToken(tree, stream, container_decl.kind_token, indent, Space.Space); // union809 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.Space); // union
657 },810 },
658 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {811 ast.Node.ContainerDecl.InitArg.Enum => |enum_tag_type| {
659 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union812 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
660813
661 const lparen = tree.nextToken(container_decl.kind_token);814 const lparen = tree.nextToken(container_decl.kind_token);
662 const enum_token = tree.nextToken(lparen);815 const enum_token = tree.nextToken(lparen);
663816
664 try renderToken(tree, stream, lparen, indent, Space.None); // (817 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
665 try renderToken(tree, stream, enum_token, indent, Space.None); // enum818 try renderToken(tree, stream, enum_token, indent, start_col, Space.None); // enum
666819
667 if (enum_tag_type) |expr| {820 if (enum_tag_type) |expr| {
668 try renderToken(tree, stream, tree.nextToken(enum_token), indent, Space.None); // (821 try renderToken(tree, stream, tree.nextToken(enum_token), indent, start_col, Space.None); // (
669 try renderExpression(allocator, stream, tree, indent, expr, Space.None);822 try renderExpression(allocator, stream, tree, indent, start_col, expr, Space.None);
670823
671 const rparen = tree.nextToken(expr.lastToken());824 const rparen = tree.nextToken(expr.lastToken());
672 try renderToken(tree, stream, rparen, indent, Space.None); // )825 try renderToken(tree, stream, rparen, indent, start_col, Space.None); // )
673 try renderToken(tree, stream, tree.nextToken(rparen), indent, Space.Space); // )826 try renderToken(tree, stream, tree.nextToken(rparen), indent, start_col, Space.Space); // )
674 } else {827 } 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); // )
676 }829 }
677 },830 },
678 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {831 ast.Node.ContainerDecl.InitArg.Type => |type_expr| {
679 try renderToken(tree, stream, container_decl.kind_token, indent, Space.None); // union832 try renderToken(tree, stream, container_decl.kind_token, indent, start_col, Space.None); // union
680833
681 const lparen = tree.nextToken(container_decl.kind_token);834 const lparen = tree.nextToken(container_decl.kind_token);
682 const rparen = tree.nextToken(type_expr.lastToken());835 const rparen = tree.nextToken(type_expr.lastToken());
683836
684 try renderToken(tree, stream, lparen, indent, Space.None); // (837 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
685 try renderExpression(allocator, stream, tree, indent, type_expr, Space.None);838 try renderExpression(allocator, stream, tree, indent, start_col, type_expr, Space.None);
686 try renderToken(tree, stream, rparen, indent, Space.Space); // )839 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
687 },840 },
688 }841 }
689842
690 if (container_decl.fields_and_decls.len == 0) {843 if (container_decl.fields_and_decls.len == 0) {
691 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, Space.None); // {844 try renderToken(tree, stream, container_decl.lbrace_token, indent + indent_delta, start_col, Space.None); // {
692 try renderToken(tree, stream, container_decl.rbrace_token, indent, space); // }845 return renderToken(tree, stream, container_decl.rbrace_token, indent, start_col, space); // }
693 } else {846 } else {
694 const new_indent = indent + indent_delta;847 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
697 var it = container_decl.fields_and_decls.iterator(0);850 var it = container_decl.fields_and_decls.iterator(0);
698 while (it.next()) |decl| {851 while (it.next()) |decl| {
699 try stream.writeByteNTimes(' ', new_indent);852 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
702 if (it.peek()) |next_decl| {855 if (it.peek()) |next_decl| {
703 try renderExtraNewline(tree, stream, next_decl.*);856 try renderExtraNewline(tree, stream, start_col, next_decl.*);
704 }857 }
705 }858 }
706859
707 try stream.writeByteNTimes(' ', indent);860 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); // }
709 }862 }
710 },863 },
711864
...@@ -715,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -715,10 +868,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
715 const lbrace = tree.nextToken(err_set_decl.error_token);868 const lbrace = tree.nextToken(err_set_decl.error_token);
716869
717 if (err_set_decl.decls.len == 0) {870 if (err_set_decl.decls.len == 0) {
718 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None);871 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None);
719 try renderToken(tree, stream, lbrace, indent, Space.None);872 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
720 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space);873 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space);
721 return;
722 }874 }
723875
724 if (err_set_decl.decls.len == 1) blk: {876 if (err_set_decl.decls.len == 1) blk: {
...@@ -732,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -732,15 +884,14 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
732 break :blk;884 break :blk;
733 }885 }
734886
735 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error887 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
736 try renderToken(tree, stream, lbrace, indent, Space.None); // {888 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
737 try renderExpression(allocator, stream, tree, indent, node, Space.None);889 try renderExpression(allocator, stream, tree, indent, start_col, node, Space.None);
738 try renderToken(tree, stream, err_set_decl.rbrace_token, indent, space); // }890 return renderToken(tree, stream, err_set_decl.rbrace_token, indent, start_col, space); // }
739 return;
740 }891 }
741892
742 try renderToken(tree, stream, err_set_decl.error_token, indent, Space.None); // error893 try renderToken(tree, stream, err_set_decl.error_token, indent, start_col, Space.None); // error
743 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {894 try renderToken(tree, stream, lbrace, indent, start_col, Space.Newline); // {
744 const new_indent = indent + indent_delta;895 const new_indent = indent + indent_delta;
745896
746 var it = err_set_decl.decls.iterator(0);897 var it = err_set_decl.decls.iterator(0);
...@@ -748,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -748,24 +899,24 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
748 try stream.writeByteNTimes(' ', new_indent);899 try stream.writeByteNTimes(' ', new_indent);
749900
750 if (it.peek()) |next_node| {901 if (it.peek()) |next_node| {
751 try renderExpression(allocator, stream, tree, new_indent, node.*, Space.None);902 try renderExpression(allocator, stream, tree, new_indent, start_col, node.*, Space.None);
752 try renderToken(tree, stream, tree.nextToken(node.*.lastToken()), new_indent, Space.Newline); // ,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.*);
755 } else {906 } 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);
757 }908 }
758 }909 }
759910
760 try stream.writeByteNTimes(' ', indent);911 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); // }
762 },913 },
763914
764 ast.Node.Id.ErrorTag => {915 ast.Node.Id.ErrorTag => {
765 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);916 const tag = @fieldParentPtr(ast.Node.ErrorTag, "base", base);
766917
767 try renderDocComments(tree, stream, tag, indent);918 try renderDocComments(tree, stream, tag, indent, start_col);
768 try renderToken(tree, stream, tag.name_token, indent, space); // name919 return renderToken(tree, stream, tag.name_token, indent, start_col, space); // name
769 },920 },
770921
771 ast.Node.Id.MultilineStringLiteral => {922 ast.Node.Id.MultilineStringLiteral => {
...@@ -783,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -783,32 +934,32 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
783 if (!skip_first_indent) {934 if (!skip_first_indent) {
784 try stream.writeByteNTimes(' ', indent + indent_delta);935 try stream.writeByteNTimes(' ', indent + indent_delta);
785 }936 }
786 try renderToken(tree, stream, t, indent, Space.None);937 try renderToken(tree, stream, t, indent, start_col, Space.None);
787 skip_first_indent = false;938 skip_first_indent = false;
788 }939 }
789 try stream.writeByteNTimes(' ', indent);940 try stream.writeByteNTimes(' ', indent);
790 },941 },
791 ast.Node.Id.UndefinedLiteral => {942 ast.Node.Id.UndefinedLiteral => {
792 const undefined_literal = @fieldParentPtr(ast.Node.UndefinedLiteral, "base", base);943 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);
794 },945 },
795946
796 ast.Node.Id.BuiltinCall => {947 ast.Node.Id.BuiltinCall => {
797 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);948 const builtin_call = @fieldParentPtr(ast.Node.BuiltinCall, "base", base);
798949
799 try renderToken(tree, stream, builtin_call.builtin_token, indent, Space.None); // @name950 try renderToken(tree, stream, builtin_call.builtin_token, indent, start_col, Space.None); // @name
800 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, Space.None); // (951 try renderToken(tree, stream, tree.nextToken(builtin_call.builtin_token), indent, start_col, Space.None); // (
801952
802 var it = builtin_call.params.iterator(0);953 var it = builtin_call.params.iterator(0);
803 while (it.next()) |param_node| {954 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
806 if (it.peek() != null) {957 if (it.peek() != null) {
807 const comma_token = tree.nextToken(param_node.*.lastToken());958 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); // ,
809 }960 }
810 }961 }
811 try renderToken(tree, stream, builtin_call.rparen_token, indent, space); // )962 return renderToken(tree, stream, builtin_call.rparen_token, indent, start_col, space); // )
812 },963 },
813964
814 ast.Node.Id.FnProto => {965 ast.Node.Id.FnProto => {
...@@ -818,68 +969,94 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -818,68 +969,94 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
818 const visib_token = tree.tokens.at(visib_token_index);969 const visib_token = tree.tokens.at(visib_token_index);
819 assert(visib_token.id == Token.Id.Keyword_pub or visib_token.id == Token.Id.Keyword_export);970 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); // pub972 try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub
822 }973 }
823974
824 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {975 if (fn_proto.extern_export_inline_token) |extern_export_inline_token| {
825 try renderToken(tree, stream, extern_export_inline_token, indent, Space.Space); // extern/export976 try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export
826 }977 }
827978
828 if (fn_proto.lib_name) |lib_name| {979 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);
830 }981 }
831982
832 if (fn_proto.cc_token) |cc_token| {983 if (fn_proto.cc_token) |cc_token| {
833 try renderToken(tree, stream, cc_token, indent, Space.Space); // stdcallcc984 try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc
834 }985 }
835986
836 if (fn_proto.async_attr) |async_attr| {987 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);
838 }989 }
839990
840 if (fn_proto.name_token) |name_token| blk: {991 const lparen = if (fn_proto.name_token) |name_token| blk: {
841 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.Space); // fn992 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn
842 try renderToken(tree, stream, name_token, indent, Space.None); // name993 try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name
843 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.None); // (994 break :blk tree.nextToken(name_token);
844 } else blk: {995 } else blk: {
845 try renderToken(tree, stream, fn_proto.fn_token, indent, Space.None); // fn996 try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.None); // fn
846 try renderToken(tree, stream, tree.nextToken(fn_proto.fn_token), indent, Space.None); // (997 break :blk tree.nextToken(fn_proto.fn_token);
847 }998 };
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 }
858999
859 const rparen = tree.prevToken(switch (fn_proto.return_type) {1000 const rparen = tree.prevToken(switch (fn_proto.return_type) {
860 ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(),1001 ast.Node.FnProto.ReturnType.Explicit => |node| node.firstToken(),
861 ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()),1002 ast.Node.FnProto.ReturnType.InferErrorSet => |node| tree.prevToken(node.firstToken()),
862 });1003 });
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
865 if (fn_proto.align_expr) |align_expr| {1042 if (fn_proto.align_expr) |align_expr| {
866 const align_rparen = tree.nextToken(align_expr.lastToken());1043 const align_rparen = tree.nextToken(align_expr.lastToken());
867 const align_lparen = tree.prevToken(align_expr.firstToken());1044 const align_lparen = tree.prevToken(align_expr.firstToken());
868 const align_kw = tree.prevToken(align_lparen);1045 const align_kw = tree.prevToken(align_lparen);
8691046
870 try renderToken(tree, stream, align_kw, indent, Space.None); // align1047 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
871 try renderToken(tree, stream, align_lparen, indent, Space.None); // (1048 try renderToken(tree, stream, align_lparen, indent, start_col, Space.None); // (
872 try renderExpression(allocator, stream, tree, indent, align_expr, Space.None);1049 try renderExpression(allocator, stream, tree, indent, start_col, align_expr, Space.None);
873 try renderToken(tree, stream, align_rparen, indent, Space.Space); // )1050 try renderToken(tree, stream, align_rparen, indent, start_col, Space.Space); // )
874 }1051 }
8751052
876 switch (fn_proto.return_type) {1053 switch (fn_proto.return_type) {
877 ast.Node.FnProto.ReturnType.Explicit => |node| {1054 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);
879 },1056 },
880 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {1057 ast.Node.FnProto.ReturnType.InferErrorSet => |node| {
881 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, Space.None); // !1058 try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // !
882 try renderExpression(allocator, stream, tree, indent, node, space);1059 return renderExpression(allocator, stream, tree, indent, start_col, node, space);
883 },1060 },
884 }1061 }
885 },1062 },
...@@ -888,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -888,11 +1065,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
888 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);1065 const promise_type = @fieldParentPtr(ast.Node.PromiseType, "base", base);
8891066
890 if (promise_type.result) |result| {1067 if (promise_type.result) |result| {
891 try renderToken(tree, stream, promise_type.promise_token, indent, Space.None); // promise1068 try renderToken(tree, stream, promise_type.promise_token, indent, start_col, Space.None); // promise
892 try renderToken(tree, stream, result.arrow_token, indent, Space.None); // ->1069 try renderToken(tree, stream, result.arrow_token, indent, start_col, Space.None); // ->
893 try renderExpression(allocator, stream, tree, indent, result.return_type, space);1070 return renderExpression(allocator, stream, tree, indent, start_col, result.return_type, space);
894 } else {1071 } else {
895 try renderToken(tree, stream, promise_type.promise_token, indent, space); // promise1072 return renderToken(tree, stream, promise_type.promise_token, indent, start_col, space); // promise
896 }1073 }
897 },1074 },
8981075
...@@ -901,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -901,39 +1078,38 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
901 ast.Node.Id.Switch => {1078 ast.Node.Id.Switch => {
902 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);1079 const switch_node = @fieldParentPtr(ast.Node.Switch, "base", base);
9031080
904 try renderToken(tree, stream, switch_node.switch_token, indent, Space.Space); // switch1081 try renderToken(tree, stream, switch_node.switch_token, indent, start_col, Space.Space); // switch
905 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, Space.None); // (1082 try renderToken(tree, stream, tree.nextToken(switch_node.switch_token), indent, start_col, Space.None); // (
9061083
907 const rparen = tree.nextToken(switch_node.expr.lastToken());1084 const rparen = tree.nextToken(switch_node.expr.lastToken());
908 const lbrace = tree.nextToken(rparen);1085 const lbrace = tree.nextToken(rparen);
9091086
910 if (switch_node.cases.len == 0) {1087 if (switch_node.cases.len == 0) {
911 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);1088 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
912 try renderToken(tree, stream, rparen, indent, Space.Space); // )1089 try renderToken(tree, stream, rparen, indent, start_col, Space.Space); // )
913 try renderToken(tree, stream, lbrace, indent, Space.None); // {1090 try renderToken(tree, stream, lbrace, indent, start_col, Space.None); // {
914 try renderToken(tree, stream, switch_node.rbrace, indent, space); // }1091 return renderToken(tree, stream, switch_node.rbrace, indent, start_col, space); // }
915 return;
916 }1092 }
9171093
918 try renderExpression(allocator, stream, tree, indent, switch_node.expr, Space.None);1094 try renderExpression(allocator, stream, tree, indent, start_col, switch_node.expr, Space.None);
919
920 try renderToken(tree, stream, rparen, indent, Space.Space); // )
921 try renderToken(tree, stream, lbrace, indent, Space.Newline); // {
9221095
923 const new_indent = indent + indent_delta;1096 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
925 var it = switch_node.cases.iterator(0);1101 var it = switch_node.cases.iterator(0);
926 while (it.next()) |node| {1102 while (it.next()) |node| {
927 try stream.writeByteNTimes(' ', new_indent);1103 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
930 if (it.peek()) |next_node| {1106 if (it.peek()) |next_node| {
931 try renderExtraNewline(tree, stream, next_node.*);1107 try renderExtraNewline(tree, stream, start_col, next_node.*);
932 }1108 }
933 }1109 }
9341110
935 try stream.writeByteNTimes(' ', indent);1111 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); // }
937 },1113 },
9381114
939 ast.Node.Id.SwitchCase => {1115 ast.Node.Id.SwitchCase => {
...@@ -950,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -950,13 +1126,13 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
950 var it = switch_case.items.iterator(0);1126 var it = switch_case.items.iterator(0);
951 while (it.next()) |node| {1127 while (it.next()) |node| {
952 if (it.peek()) |next_node| {1128 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
955 const comma_token = tree.nextToken(node.*.lastToken());1131 const comma_token = tree.nextToken(node.*.lastToken());
956 try renderToken(tree, stream, comma_token, indent, Space.Space); // ,1132 try renderToken(tree, stream, comma_token, indent, start_col, Space.Space); // ,
957 try renderExtraNewline(tree, stream, next_node.*);1133 try renderExtraNewline(tree, stream, start_col, next_node.*);
958 } else {1134 } else {
959 try renderExpression(allocator, stream, tree, indent, node.*, Space.Space);1135 try renderExpression(allocator, stream, tree, indent, start_col, node.*, Space.Space);
960 }1136 }
961 }1137 }
962 } else {1138 } else {
...@@ -964,84 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -964,84 +1140,97 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
964 while (true) {1140 while (true) {
965 const node = ??it.next();1141 const node = ??it.next();
966 if (it.peek()) |next_node| {1142 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
969 const comma_token = tree.nextToken(node.*.lastToken());1145 const comma_token = tree.nextToken(node.*.lastToken());
970 try renderToken(tree, stream, comma_token, indent, Space.Newline); // ,1146 try renderToken(tree, stream, comma_token, indent, start_col, Space.Newline); // ,
971 try renderExtraNewline(tree, stream, next_node.*);1147 try renderExtraNewline(tree, stream, start_col, next_node.*);
972 try stream.writeByteNTimes(' ', indent);1148 try stream.writeByteNTimes(' ', indent);
973 } else {1149 } 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);
975 break;1152 break;
976 }1153 }
977 }1154 }
978 }1155 }
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
982 if (switch_case.payload) |payload| {1159 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);
984 }1161 }
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);
987 },1164 },
988 ast.Node.Id.SwitchElse => {1165 ast.Node.Id.SwitchElse => {
989 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);1166 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);
991 },1168 },
992 ast.Node.Id.Else => {1169 ast.Node.Id.Else => {
993 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);1170 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
9941171
995 const block_body = switch (else_node.body.id) {1172 const body_is_block = nodeIsBlock(else_node.body);
996 ast.Node.Id.Block,1173 const same_line = body_is_block or tree.tokensOnSameLine(else_node.else_token, else_node.body.lastToken());
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 };
10031174
1004 const after_else_space = if (block_body or else_node.payload != null) Space.Space else Space.Newline;1175 const after_else_space = if (same_line or else_node.payload != null) Space.Space else Space.Newline;
1005 try renderToken(tree, stream, else_node.else_token, indent, after_else_space);1176 try renderToken(tree, stream, else_node.else_token, indent, start_col, after_else_space);
10061177
1007 if (else_node.payload) |payload| {1178 if (else_node.payload) |payload| {
1008 const payload_space = if (block_body) Space.Space else Space.Newline;1179 const payload_space = if (same_line) Space.Space else Space.Newline;
1009 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1180 try renderExpression(allocator, stream, tree, indent, start_col, payload, payload_space);
1010 }1181 }
10111182
1012 if (block_body) {1183 if (same_line) {
1013 try renderExpression(allocator, stream, tree, indent, else_node.body, space);1184 return renderExpression(allocator, stream, tree, indent, start_col, else_node.body, space);
1014 } else {
1015 try stream.writeByteNTimes(' ', indent + indent_delta);
1016 try renderExpression(allocator, stream, tree, indent, else_node.body, space);
1017 }1185 }
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);
1018 },1190 },
10191191
1020 ast.Node.Id.While => {1192 ast.Node.Id.While => {
1021 const while_node = @fieldParentPtr(ast.Node.While, "base", base);1193 const while_node = @fieldParentPtr(ast.Node.While, "base", base);
10221194
1023 if (while_node.label) |label| {1195 if (while_node.label) |label| {
1024 try renderToken(tree, stream, label, indent, Space.None); // label1196 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1025 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :1197 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
1026 }1198 }
10271199
1028 if (while_node.inline_token) |inline_token| {1200 if (while_node.inline_token) |inline_token| {
1029 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline1201 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
1030 }1202 }
10311203
1032 try renderToken(tree, stream, while_node.while_token, indent, Space.Space); // while1204 try renderToken(tree, stream, while_node.while_token, indent, start_col, Space.Space); // while
1033 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, Space.None); // (1205 try renderToken(tree, stream, tree.nextToken(while_node.while_token), indent, start_col, Space.None); // (
1034 try renderExpression(allocator, stream, tree, indent, while_node.condition, 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
1036 {1226 {
1037 const rparen = tree.nextToken(while_node.condition.lastToken());1227 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null) Space.Space else block_start_space;
1038 const rparen_space = if (while_node.payload != null or while_node.continue_expr != null or1228 try renderToken(tree, stream, cond_rparen, indent, start_col, rparen_space); // )
1039 while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;
1040 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1041 }1229 }
10421230
1043 if (while_node.payload) |payload| {1231 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);
1045 }1234 }
10461235
1047 if (while_node.continue_expr) |continue_expr| {1236 if (while_node.continue_expr) |continue_expr| {
...@@ -1049,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1049,37 +1238,29 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1049 const lparen = tree.prevToken(continue_expr.firstToken());1238 const lparen = tree.prevToken(continue_expr.firstToken());
1050 const colon = tree.prevToken(lparen);1239 const colon = tree.prevToken(lparen);
10511240
1052 try renderToken(tree, stream, colon, indent, Space.Space); // :1241 try renderToken(tree, stream, colon, indent, start_col, Space.Space); // :
1053 try renderToken(tree, stream, lparen, indent, Space.None); // (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;1246 try renderToken(tree, stream, rparen, indent, start_col, block_start_space); // )
1058 try renderToken(tree, stream, rparen, indent, rparen_space); // )
1059 }1247 }
10601248
1061 const body_space = blk: {1249 var new_indent = indent;
1062 if (while_node.@"else" != null) {1250 if (block_start_space == Space.Newline) {
1063 break :blk if (while_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1251 new_indent += indent_delta;
1064 } else {1252 try stream.writeByteNTimes(' ', new_indent);
1065 break :blk space;1253 start_col.* = new_indent;
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);
1074 }1254 }
10751255
1256 try renderExpression(allocator, stream, tree, indent, start_col, while_node.body, after_body_space);
1257
1076 if (while_node.@"else") |@"else"| {1258 if (while_node.@"else") |@"else"| {
1077 if (while_node.body.id == ast.Node.Id.Block) {1259 if (after_body_space == Space.Newline) {
1078 } else {
1079 try stream.writeByteNTimes(' ', indent);1260 try stream.writeByteNTimes(' ', indent);
1261 start_col.* = indent;
1080 }1262 }
10811263 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1082 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);
1083 }1264 }
1084 },1265 },
10851266
...@@ -1087,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1087,26 +1268,26 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1087 const for_node = @fieldParentPtr(ast.Node.For, "base", base);1268 const for_node = @fieldParentPtr(ast.Node.For, "base", base);
10881269
1089 if (for_node.label) |label| {1270 if (for_node.label) |label| {
1090 try renderToken(tree, stream, label, indent, Space.None); // label1271 try renderToken(tree, stream, label, indent, start_col, Space.None); // label
1091 try renderToken(tree, stream, tree.nextToken(label), indent, Space.Space); // :1272 try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space); // :
1092 }1273 }
10931274
1094 if (for_node.inline_token) |inline_token| {1275 if (for_node.inline_token) |inline_token| {
1095 try renderToken(tree, stream, inline_token, indent, Space.Space); // inline1276 try renderToken(tree, stream, inline_token, indent, start_col, Space.Space); // inline
1096 }1277 }
10971278
1098 try renderToken(tree, stream, for_node.for_token, indent, Space.Space); // for1279 try renderToken(tree, stream, for_node.for_token, indent, start_col, Space.Space); // for
1099 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, Space.None); // (1280 try renderToken(tree, stream, tree.nextToken(for_node.for_token), indent, start_col, Space.None); // (
1100 try renderExpression(allocator, stream, tree, indent, for_node.array_expr, Space.None);1281 try renderExpression(allocator, stream, tree, indent, start_col, for_node.array_expr, Space.None);
11011282
1102 const rparen = tree.nextToken(for_node.array_expr.lastToken());1283 const rparen = tree.nextToken(for_node.array_expr.lastToken());
1103 const rparen_space = if (for_node.payload != null or1284 const rparen_space = if (for_node.payload != null or
1104 for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1285 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
1107 if (for_node.payload) |payload| {1288 if (for_node.payload) |payload| {
1108 const payload_space = if (for_node.body.id == ast.Node.Id.Block) Space.Space else Space.Newline;1289 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);
1110 }1291 }
11111292
1112 const body_space = blk: {1293 const body_space = blk: {
...@@ -1121,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1121,10 +1302,10 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1121 }1302 }
1122 };1303 };
1123 if (for_node.body.id == ast.Node.Id.Block) {1304 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);
1125 } else {1306 } else {
1126 try stream.writeByteNTimes(' ', indent + indent_delta);1307 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);
1128 }1309 }
11291310
1130 if (for_node.@"else") |@"else"| {1311 if (for_node.@"else") |@"else"| {
...@@ -1132,167 +1313,252 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1132,167 +1313,252 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1132 try stream.writeByteNTimes(' ', indent);1313 try stream.writeByteNTimes(' ', indent);
1133 }1314 }
11341315
1135 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);1316 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1136 }1317 }
1137 },1318 },
11381319
1139 ast.Node.Id.If => {1320 ast.Node.Id.If => {
1140 const if_node = @fieldParentPtr(ast.Node.If, "base", base);1321 const if_node = @fieldParentPtr(ast.Node.If, "base", base);
11411322
1142 try renderToken(tree, stream, if_node.if_token, indent, Space.Space);1323 const lparen = tree.prevToken(if_node.condition.firstToken());
1143 try renderToken(tree, stream, tree.prevToken(if_node.condition.firstToken()), indent, Space.None);1324 const rparen = tree.nextToken(if_node.condition.lastToken());
11441325
1145 try renderExpression(allocator, stream, tree, indent, if_node.condition, Space.None);1326 try renderToken(tree, stream, if_node.if_token, indent, start_col, Space.Space); // if
1146 try renderToken(tree, stream, tree.nextToken(if_node.condition.lastToken()), indent, Space.Space);1327 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
11471328
1148 if (if_node.payload) |payload| {1329 try renderExpression(allocator, stream, tree, indent, start_col, if_node.condition, Space.None); // condition
1149 try renderExpression(allocator, stream, tree, indent, payload, Space.Space);1330
1150 }1331 const body_is_block = nodeIsBlock(if_node.body);
11511332
1152 switch (if_node.body.id) {1333 if (body_is_block) {
1153 ast.Node.Id.Block,1334 const after_rparen_space = if (if_node.payload == null) Space.BlockStart else Space.Space;
1154 ast.Node.Id.If,1335 try renderToken(tree, stream, rparen, indent, start_col, after_rparen_space); // )
1155 ast.Node.Id.For,1336
1156 ast.Node.Id.While,1337 if (if_node.payload) |payload| {
1157 ast.Node.Id.Switch => {1338 try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.BlockStart); // |x|
1158 if (if_node.@"else") |@"else"| {1339 }
1159 if (if_node.body.id == ast.Node.Id.Block) {1340
1160 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Space);1341 if (if_node.@"else") |@"else"| {
1161 } else {1342 try renderExpression(allocator, stream, tree, indent, start_col, if_node.body, Space.SpaceOrOutdent);
1162 try renderExpression(allocator, stream, tree, indent, if_node.body, Space.Newline);1343 return renderExpression(allocator, stream, tree, indent, start_col, &@"else".base, space);
1163 try stream.writeByteNTimes(' ', indent);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);
1164 }1372 }
11651373
1166 try renderExpression(allocator, stream, tree, indent, &@"else".base, space);1374 return renderExpression(allocator, stream, tree, indent, start_col, @"else".body, space);
1167 } else {1375 } else {
1168 try renderExpression(allocator, stream, tree, indent, if_node.body, space);1376 const after_else_space = if (@"else".payload == null) Space.Newline else Space.Space;
1169 }1377 try renderToken(tree, stream, @"else".else_token, indent, start_col, after_else_space); // else
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);
11751378
1176 if (@"else".payload) |payload| {1379 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);
1178 }1381 }
1382 try stream.writeByteNTimes(' ', new_indent);
11791383
1180 try renderExpression(allocator, stream, tree, indent, @"else".body, space);1384 return renderExpression(allocator, stream, tree, new_indent, start_col, @"else".body, space);
1181 } else {
1182 try renderExpression(allocator, stream, tree, indent, if_node.body, space);
1183 }1385 }
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);
1185 }1408 }
1186 },1409 },
11871410
1188 ast.Node.Id.Asm => {1411 ast.Node.Id.Asm => {
1189 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);1412 const asm_node = @fieldParentPtr(ast.Node.Asm, "base", base);
11901413
1191 try renderToken(tree, stream, asm_node.asm_token, indent, Space.Space); // asm1414 try renderToken(tree, stream, asm_node.asm_token, indent, start_col, Space.Space); // asm
11921415
1193 if (asm_node.volatile_token) |volatile_token| {1416 if (asm_node.volatile_token) |volatile_token| {
1194 try renderToken(tree, stream, volatile_token, indent, Space.Space); // volatile1417 try renderToken(tree, stream, volatile_token, indent, start_col, Space.Space); // volatile
1195 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, Space.None); // (1418 try renderToken(tree, stream, tree.nextToken(volatile_token), indent, start_col, Space.None); // (
1196 } else {1419 } 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);
1198 }1426 }
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
1201 const indent_once = indent + indent_delta;1430 const indent_once = indent + indent_delta;
1202 try stream.writeByteNTimes(' ', indent_once);1431 try stream.writeByteNTimes(' ', indent_once);
1203 try stream.print(": ");1432
1433 const colon1 = tree.nextToken(asm_node.template.lastToken());
1204 const indent_extra = indent_once + 2;1434 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
1207 var it = asm_node.outputs.iterator(0);1444 var it = asm_node.outputs.iterator(0);
1208 while (it.next()) |asm_output| {1445 while (true) {
1446 const asm_output = ??it.next();
1209 const node = &(asm_output.*).base;1447 const node = &(asm_output.*).base;
1210 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12111448
1212 if (it.peek()) |next_asm_output| {1449 if (it.peek()) |next_asm_output| {
1450 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
1213 const next_node = &(next_asm_output.*).base;1451 const next_node = &(next_asm_output.*).base;
12141452
1215 const comma = tree.prevToken(next_asm_output.*.firstToken());1453 const comma = tree.prevToken(next_asm_output.*.firstToken());
1216 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,1454 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1217 try renderExtraNewline(tree, stream, next_node);1455 try renderExtraNewline(tree, stream, start_col, next_node);
12181456
1219 try stream.writeByteNTimes(' ', indent_extra);1457 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 };
1220 }1470 }
1221 }1471 }
1222 }1472 };
12231473
1224 try stream.write("\n");1474 const colon3 = if (asm_node.inputs.len == 0) blk: {
1225 try stream.writeByteNTimes(' ', indent_once);1475 try renderToken(tree, stream, colon2, indent, start_col, Space.Newline); // :
1226 try stream.write(": ");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 {
1229 var it = asm_node.inputs.iterator(0);1482 var it = asm_node.inputs.iterator(0);
1230 while (it.next()) |asm_input| {1483 while (true) {
1484 const asm_input = ??it.next();
1231 const node = &(asm_input.*).base;1485 const node = &(asm_input.*).base;
1232 try renderExpression(allocator, stream, tree, indent_extra, node, Space.None);
12331486
1234 if (it.peek()) |next_asm_input| {1487 if (it.peek()) |next_asm_input| {
1488 try renderExpression(allocator, stream, tree, indent_extra, start_col, node, Space.None);
1235 const next_node = &(next_asm_input.*).base;1489 const next_node = &(next_asm_input.*).base;
12361490
1237 const comma = tree.prevToken(next_asm_input.*.firstToken());1491 const comma = tree.prevToken(next_asm_input.*.firstToken());
1238 try renderToken(tree, stream, comma, indent_extra, Space.Newline); // ,1492 try renderToken(tree, stream, comma, indent_extra, start_col, Space.Newline); // ,
1239 try renderExtraNewline(tree, stream, next_node);1493 try renderExtraNewline(tree, stream, start_col, next_node);
12401494
1241 try stream.writeByteNTimes(' ', indent_extra);1495 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 };
1242 }1508 }
1243 }1509 }
1244 }1510 };
12451511
1246 try stream.write("\n");1512 try renderToken(tree, stream, colon3, indent, start_col, Space.Space); // :
1247 try stream.writeByteNTimes(' ', indent_once);
1248 try stream.write(": ");
12491513
1250 {1514 var it = asm_node.clobbers.iterator(0);
1251 var it = asm_node.clobbers.iterator(0);1515 while (true) {
1252 while (it.next()) |node| {1516 const clobber_token = ??it.next();
1253 try renderExpression(allocator, stream, tree, indent_once, node.*, Space.None);
12541517
1255 if (it.peek() != null) {1518 if (it.peek() == null) {
1256 try stream.write(", ");1519 try renderToken(tree, stream, clobber_token.*, indent_once, start_col, Space.Newline);
1257 }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); // ,
1258 }1526 }
1259 }1527 }
1260
1261 try renderToken(tree, stream, asm_node.rparen, indent, space);
1262 },1528 },
12631529
1264 ast.Node.Id.AsmInput => {1530 ast.Node.Id.AsmInput => {
1265 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);1531 const asm_input = @fieldParentPtr(ast.Node.AsmInput, "base", base);
12661532
1267 try stream.write("[");1533 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);
1269 try stream.write("] ");1535 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);
1271 try stream.write(" (");1537 try stream.write(" (");
1272 try renderExpression(allocator, stream, tree, indent, asm_input.expr, Space.None);1538 try renderExpression(allocator, stream, tree, indent, start_col, asm_input.expr, Space.None);
1273 try renderToken(tree, stream, asm_input.lastToken(), indent, space); // )1539 return renderToken(tree, stream, asm_input.lastToken(), indent, start_col, space); // )
1274 },1540 },
12751541
1276 ast.Node.Id.AsmOutput => {1542 ast.Node.Id.AsmOutput => {
1277 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);1543 const asm_output = @fieldParentPtr(ast.Node.AsmOutput, "base", base);
12781544
1279 try stream.write("[");1545 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);
1281 try stream.write("] ");1547 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);
1283 try stream.write(" (");1549 try stream.write(" (");
12841550
1285 switch (asm_output.kind) {1551 switch (asm_output.kind) {
1286 ast.Node.AsmOutput.Kind.Variable => |variable_name| {1552 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);
1288 },1554 },
1289 ast.Node.AsmOutput.Kind.Return => |return_type| {1555 ast.Node.AsmOutput.Kind.Return => |return_type| {
1290 try stream.write("-> ");1556 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);
1292 },1558 },
1293 }1559 }
12941560
1295 try renderToken(tree, stream, asm_output.lastToken(), indent, space); // )1561 return renderToken(tree, stream, asm_output.lastToken(), indent, start_col, space); // )
1296 },1562 },
12971563
1298 ast.Node.Id.StructField,1564 ast.Node.Id.StructField,
...@@ -1306,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1306,92 +1572,92 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
1306 }1572 }
1307}1573}
13081574
1309fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize,1575fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, start_col: &usize,
1310 var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void1576 var_decl: &ast.Node.VarDecl,) (@typeOf(stream).Child.Error || Error)!void
1311{1577{
1312 if (var_decl.visib_token) |visib_token| {1578 if (var_decl.visib_token) |visib_token| {
1313 try renderToken(tree, stream, visib_token, indent, Space.Space); // pub1579 try renderToken(tree, stream, visib_token, indent, start_col, Space.Space); // pub
1314 }1580 }
13151581
1316 if (var_decl.extern_export_token) |extern_export_token| {1582 if (var_decl.extern_export_token) |extern_export_token| {
1317 try renderToken(tree, stream, extern_export_token, indent, Space.Space); // extern1583 try renderToken(tree, stream, extern_export_token, indent, start_col, Space.Space); // extern
13181584
1319 if (var_decl.lib_name) |lib_name| {1585 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"
1321 }1587 }
1322 }1588 }
13231589
1324 if (var_decl.comptime_token) |comptime_token| {1590 if (var_decl.comptime_token) |comptime_token| {
1325 try renderToken(tree, stream, comptime_token, indent, Space.Space); // comptime1591 try renderToken(tree, stream, comptime_token, indent, start_col, Space.Space); // comptime
1326 }1592 }
13271593
1328 try renderToken(tree, stream, var_decl.mut_token, indent, Space.Space); // var1594 try renderToken(tree, stream, var_decl.mut_token, indent, start_col, Space.Space); // var
13291595
1330 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or1596 const name_space = if (var_decl.type_node == null and (var_decl.align_node != null or
1331 var_decl.init_node != null)) Space.Space else Space.None;1597 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
1334 if (var_decl.type_node) |type_node| {1600 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);
1336 const s = if (var_decl.align_node != null or var_decl.init_node != null) Space.Space else Space.None;1602 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);
1338 }1604 }
13391605
1340 if (var_decl.align_node) |align_node| {1606 if (var_decl.align_node) |align_node| {
1341 const lparen = tree.prevToken(align_node.firstToken());1607 const lparen = tree.prevToken(align_node.firstToken());
1342 const align_kw = tree.prevToken(lparen);1608 const align_kw = tree.prevToken(lparen);
1343 const rparen = tree.nextToken(align_node.lastToken());1609 const rparen = tree.nextToken(align_node.lastToken());
1344 try renderToken(tree, stream, align_kw, indent, Space.None); // align1610 try renderToken(tree, stream, align_kw, indent, start_col, Space.None); // align
1345 try renderToken(tree, stream, lparen, indent, Space.None); // (1611 try renderToken(tree, stream, lparen, indent, start_col, Space.None); // (
1346 try renderExpression(allocator, stream, tree, indent, align_node, Space.None);1612 try renderExpression(allocator, stream, tree, indent, start_col, align_node, Space.None);
1347 const s = if (var_decl.init_node != null) Space.Space else Space.None;1613 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); // )
1349 }1615 }
13501616
1351 if (var_decl.init_node) |init_node| {1617 if (var_decl.init_node) |init_node| {
1352 const s = if (init_node.id == ast.Node.Id.MultilineStringLiteral) Space.None else Space.Space;1618 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); // =1619 try renderToken(tree, stream, var_decl.eq_token, indent, start_col, s); // =
1354 try renderExpression(allocator, stream, tree, indent, init_node, Space.None);1620 try renderExpression(allocator, stream, tree, indent, start_col, init_node, Space.None);
1355 }1621 }
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);
1358}1624}
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 {
1361 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);1627 const param_decl = @fieldParentPtr(ast.Node.ParamDecl, "base", base);
13621628
1363 if (param_decl.comptime_token) |comptime_token| {1629 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);
1365 }1631 }
1366 if (param_decl.noalias_token) |noalias_token| {1632 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);
1368 }1634 }
1369 if (param_decl.name_token) |name_token| {1635 if (param_decl.name_token) |name_token| {
1370 try renderToken(tree, stream, name_token, indent, Space.None);1636 try renderToken(tree, stream, name_token, indent, start_col, Space.None);
1371 try renderToken(tree, stream, tree.nextToken(name_token), indent, Space.Space); // :1637 try renderToken(tree, stream, tree.nextToken(name_token), indent, start_col, Space.Space); // :
1372 }1638 }
1373 if (param_decl.var_args_token) |var_args_token| {1639 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);
1375 } else {1641 } 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);
1377 }1643 }
1378}1644}
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 {
1381 switch (base.id) {1647 switch (base.id) {
1382 ast.Node.Id.VarDecl => {1648 ast.Node.Id.VarDecl => {
1383 const var_decl = @fieldParentPtr(ast.Node.VarDecl, "base", base);1649 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);
1385 },1651 },
1386 else => {1652 else => {
1387 if (base.requireSemiColon()) {1653 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
1390 const semicolon_index = tree.nextToken(base.lastToken());1656 const semicolon_index = tree.nextToken(base.lastToken());
1391 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);1657 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);
1393 } else {1659 } else {
1394 try renderExpression(allocator, stream, tree, indent, base, Space.Newline);1660 try renderExpression(allocator, stream, tree, indent, start_col, base, Space.Newline);
1395 }1661 }
1396 },1662 },
1397 }1663 }
...@@ -1400,32 +1666,95 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde...@@ -1400,32 +1666,95 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde
1400const Space = enum {1666const Space = enum {
1401 None,1667 None,
1402 Newline,1668 Newline,
1669 Comma,
1403 Space,1670 Space,
1671 SpaceOrOutdent,
1404 NoNewline,1672 NoNewline,
1405 NoIndent,
1406 NoComment,1673 NoComment,
1674 BlockStart,
1407};1675};
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
1410 var token = tree.tokens.at(token_index);1687 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
1415 var next_token = tree.tokens.at(token_index + 1);1693 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: {
1417 switch (space) {1724 switch (space) {
1418 Space.None, Space.NoNewline, Space.NoIndent => return,1725 Space.None, Space.NoNewline => return,
1419 Space.Newline => return stream.write("\n"),1726 Space.Newline => {
1420 Space.Space => return stream.writeByte(' '),1727 if (next_token.id == Token.Id.MultilineStringLiteralLine) {
1421 Space.NoComment => unreachable,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 => {},
1422 }1752 }
1423 }1753 }
14241754
1425 var loc = tree.tokenLocationPtr(token.end, next_token);1755 var loc = tree.tokenLocationPtr(token.end, next_token);
1426 var offset: usize = 1;
1427 if (loc.line == 0) {1756 if (loc.line == 0) {
1428 try stream.print(" {}", tree.tokenSlicePtr(next_token));1757 try stream.print(" {}", mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
1429 offset = 2;1758 offset = 2;
1430 token = next_token;1759 token = next_token;
1431 next_token = tree.tokens.at(token_index + offset);1760 next_token = tree.tokens.at(token_index + offset);
...@@ -1439,10 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1439,10 +1768,24 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1439 else => indent + indent_delta,1768 else => indent + indent_delta,
1440 };1769 };
1441 try stream.writeByteNTimes(' ', next_line_indent);1770 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 }
1442 },1786 },
1443 Space.Newline, Space.NoIndent => try stream.write("\n"),
1444 Space.NoNewline => {},1787 Space.NoNewline => {},
1445 Space.NoComment => unreachable,1788 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1446 }1789 }
1447 return;1790 return;
1448 }1791 }
...@@ -1454,26 +1797,40 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1454,26 +1797,40 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1454 const newline_count = if (loc.line == 1) u8(1) else u8(2);1797 const newline_count = if (loc.line == 1) u8(1) else u8(2);
1455 try stream.writeByteNTimes('\n', newline_count);1798 try stream.writeByteNTimes('\n', newline_count);
1456 try stream.writeByteNTimes(' ', indent);1799 try stream.writeByteNTimes(' ', indent);
1457 try stream.write(tree.tokenSlicePtr(next_token));1800 try stream.write(mem.trimRight(u8, tree.tokenSlicePtr(next_token), " "));
14581801
1459 offset += 1;1802 offset += 1;
1460 token = next_token;1803 token = next_token;
1461 next_token = tree.tokens.at(token_index + offset);1804 next_token = tree.tokens.at(token_index + offset);
1462 if (next_token.id != Token.Id.LineComment) {1805 if (next_token.id != Token.Id.LineComment) {
1463 switch (space) {1806 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 },
1465 Space.None, Space.Space => {1816 Space.None, Space.Space => {
1466 try stream.writeByte('\n');1817 try stream.writeByte('\n');
14671818
1468 const after_comment_token = tree.tokens.at(token_index + offset);1819 const after_comment_token = tree.tokens.at(token_index + offset);
1469 const next_line_indent = switch (after_comment_token.id) {1820 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,
1471 else => indent,1822 else => indent,
1472 };1823 };
1473 try stream.writeByteNTimes(' ', next_line_indent);1824 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;
1474 },1831 },
1475 Space.NoNewline => {},1832 Space.NoNewline => {},
1476 Space.NoComment => unreachable,1833 Space.NoComment, Space.Comma, Space.BlockStart => unreachable,
1477 }1834 }
1478 return;1835 return;
1479 }1836 }
...@@ -1481,33 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1481,33 +1838,30 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1481 }1838 }
1482}1839}
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 {
1485 const comment = node.doc_comments ?? return;1842 const comment = node.doc_comments ?? return;
1486 var it = comment.lines.iterator(0);1843 var it = comment.lines.iterator(0);
1844 const first_token = node.firstToken();
1487 while (it.next()) |line_token_index| {1845 while (it.next()) |line_token_index| {
1488 try renderToken(tree, stream, line_token_index.*, indent, Space.Newline);1846 if (line_token_index.* < first_token) {
1489 try stream.writeByteNTimes(' ', indent);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 }
1490 }1854 }
1491}1855}
14921856
1493fn renderTrailingComma(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node,1857fn nodeIsBlock(base: &const ast.Node) bool {
1494 space: Space) (@typeOf(stream).Child.Error || Error)!void1858 return switch (base.id) {
1495{1859 ast.Node.Id.Block,
1496 const end_token = base.lastToken() + 1;1860 ast.Node.Id.If,
1497 switch (tree.tokens.at(end_token).id) {1861 ast.Node.Id.For,
1498 Token.Id.Comma => {1862 ast.Node.Id.While,
1499 try renderExpression(allocator, stream, tree, indent, base, Space.None);1863 ast.Node.Id.Switch,
1500 try renderToken(tree, stream, end_token, indent, space); // ,1864 => true,
1501 },1865 else => false,
1502 Token.Id.LineComment => {1866 };
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 }
1513}1867}
std/zig/tokenizer.zig-12
...@@ -217,7 +217,6 @@ pub const Tokenizer = struct {...@@ -217,7 +217,6 @@ pub const Tokenizer = struct {
217 StringLiteral,217 StringLiteral,
218 StringLiteralBackslash,218 StringLiteralBackslash,
219 MultilineStringLiteralLine,219 MultilineStringLiteralLine,
220 MultilineStringLiteralLineBackslash,
221 CharLiteral,220 CharLiteral,
222 CharLiteralBackslash,221 CharLiteralBackslash,
223 CharLiteralEscape1,222 CharLiteralEscape1,
...@@ -655,9 +654,6 @@ pub const Tokenizer = struct {...@@ -655,9 +654,6 @@ pub const Tokenizer = struct {
655 },654 },
656655
657 State.MultilineStringLiteralLine => switch (c) {656 State.MultilineStringLiteralLine => switch (c) {
658 '\\' => {
659 state = State.MultilineStringLiteralLineBackslash;
660 },
661 '\n' => {657 '\n' => {
662 self.index += 1;658 self.index += 1;
663 break;659 break;
...@@ -665,13 +661,6 @@ pub const Tokenizer = struct {...@@ -665,13 +661,6 @@ pub const Tokenizer = struct {
665 else => self.checkLiteralCharacter(),661 else => self.checkLiteralCharacter(),
666 },662 },
667663
668 State.MultilineStringLiteralLineBackslash => switch (c) {
669 '\n' => break, // Look for this error later.
670 else => {
671 state = State.MultilineStringLiteralLine;
672 },
673 },
674
675 State.Bang => switch (c) {664 State.Bang => switch (c) {
676 '=' => {665 '=' => {
677 result.id = Token.Id.BangEqual;666 result.id = Token.Id.BangEqual;
...@@ -1010,7 +999,6 @@ pub const Tokenizer = struct {...@@ -1010,7 +999,6 @@ pub const Tokenizer = struct {
1010 State.FloatExponentUnsignedHex,999 State.FloatExponentUnsignedHex,
1011 State.SawAtSign,1000 State.SawAtSign,
1012 State.Backslash,1001 State.Backslash,
1013 State.MultilineStringLiteralLineBackslash,
1014 State.CharLiteral,1002 State.CharLiteral,
1015 State.CharLiteralBackslash,1003 State.CharLiteralBackslash,
1016 State.CharLiteralEscape1,1004 State.CharLiteralEscape1,