authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-17 00:56:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-17 00:56:35-04:00
log99fc2bd4ddbe36994153f6426f0001d338e90bef
treee5f2be82ac4ae7793212d218ff20422912fd5d32
parentb73307befb49dd3b131d99ecf1c7f3fb54578ec8
parent942d384831196acf24868c32ef84409b05441960

Merge remote-tracking branch 'origin/master' into pointer-reform


6 files changed, 215 insertions(+), 53 deletions(-)

src/target.cpp+1-1
...@@ -702,6 +702,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -702,6 +702,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
702 case OsLinux:702 case OsLinux:
703 case OsMacOSX:703 case OsMacOSX:
704 case OsZen:704 case OsZen:
705 case OsOpenBSD:
705 switch (id) {706 switch (id) {
706 case CIntTypeShort:707 case CIntTypeShort:
707 case CIntTypeUShort:708 case CIntTypeUShort:
...@@ -742,7 +743,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {...@@ -742,7 +743,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
742 case OsKFreeBSD:743 case OsKFreeBSD:
743 case OsLv2:744 case OsLv2:
744 case OsNetBSD:745 case OsNetBSD:
745 case OsOpenBSD:
746 case OsSolaris:746 case OsSolaris:
747 case OsHaiku:747 case OsHaiku:
748 case OsMinix:748 case OsMinix:
std/fmt/index.zig+58-29
...@@ -26,6 +26,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),...@@ -26,6 +26,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
26 Buf,26 Buf,
27 BufWidth,27 BufWidth,
28 Bytes,28 Bytes,
29 BytesBase,
29 BytesWidth,30 BytesWidth,
30 };31 };
3132
...@@ -97,6 +98,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),...@@ -97,6 +98,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
97 },98 },
98 'B' => {99 'B' => {
99 width = 0;100 width = 0;
101 radix = 1000;
100 state = State.Bytes;102 state = State.Bytes;
101 },103 },
102 else => @compileError("Unknown format character: " ++ []u8{c}),104 else => @compileError("Unknown format character: " ++ []u8{c}),
...@@ -212,7 +214,24 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),...@@ -212,7 +214,24 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
212 },214 },
213 State.Bytes => switch (c) {215 State.Bytes => switch (c) {
214 '}' => {216 '}' => {
215 try formatBytes(args[next_arg], 0, context, Errors, output);217 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
218 next_arg += 1;
219 state = State.Start;
220 start_index = i + 1;
221 },
222 'i' => {
223 radix = 1024;
224 state = State.BytesBase;
225 },
226 '0' ... '9' => {
227 width_start = i;
228 state = State.BytesWidth;
229 },
230 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
231 },
232 State.BytesBase => switch (c) {
233 '}' => {
234 try formatBytes(args[next_arg], 0, radix, context, Errors, output);
216 next_arg += 1;235 next_arg += 1;
217 state = State.Start;236 state = State.Start;
218 start_index = i + 1;237 start_index = i + 1;
...@@ -226,7 +245,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),...@@ -226,7 +245,7 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
226 State.BytesWidth => switch (c) {245 State.BytesWidth => switch (c) {
227 '}' => {246 '}' => {
228 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);247 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
229 try formatBytes(args[next_arg], width, context, Errors, output);248 try formatBytes(args[next_arg], width, radix, context, Errors, output);
230 next_arg += 1;249 next_arg += 1;
231 state = State.Start;250 state = State.Start;
232 start_index = i + 1;251 start_index = i + 1;
...@@ -543,7 +562,7 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com...@@ -543,7 +562,7 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
543 }562 }
544}563}
545564
546pub fn formatBytes(value: var, width: ?usize,565pub fn formatBytes(value: var, width: ?usize, comptime radix: usize,
547 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void566 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
548{567{
549 if (value == 0) {568 if (value == 0) {
...@@ -551,16 +570,26 @@ pub fn formatBytes(value: var, width: ?usize,...@@ -551,16 +570,26 @@ pub fn formatBytes(value: var, width: ?usize,
551 }570 }
552571
553 const mags = " KMGTPEZY";572 const mags = " KMGTPEZY";
554 const magnitude = math.min(math.log2(value) / 10, mags.len - 1);573 const magnitude = switch (radix) {
555 const new_value = f64(value) / math.pow(f64, 1024, f64(magnitude));574 1000 => math.min(math.log2(value) / comptime math.log2(1000), mags.len - 1),
575 1024 => math.min(math.log2(value) / 10, mags.len - 1),
576 else => unreachable,
577 };
578 const new_value = f64(value) / math.pow(f64, f64(radix), f64(magnitude));
556 const suffix = mags[magnitude];579 const suffix = mags[magnitude];
557580
558 try formatFloatDecimal(new_value, width, context, Errors, output);581 try formatFloatDecimal(new_value, width, context, Errors, output);
559582
560 if (suffix != ' ') {583 if (suffix == ' ') {
561 try output(context, (&suffix)[0..1]);584 return output(context, "B");
562 }585 }
563 return output(context, "B");586
587 const buf = switch (radix) {
588 1000 => []u8 { suffix, 'B' },
589 1024 => []u8 { suffix, 'i', 'B' },
590 else => unreachable,
591 };
592 return output(context, buf);
564}593}
565594
566pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,595pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
...@@ -773,41 +802,27 @@ test "parse unsigned comptime" {...@@ -773,41 +802,27 @@ test "parse unsigned comptime" {
773802
774test "fmt.format" {803test "fmt.format" {
775 {804 {
776 var buf1: [32]u8 = undefined;
777 const value: ?i32 = 1234;805 const value: ?i32 = 1234;
778 const result = try bufPrint(buf1[0..], "nullable: {}\n", value);806 try testFmt("nullable: 1234\n", "nullable: {}\n", value);
779 assert(mem.eql(u8, result, "nullable: 1234\n"));
780 }807 }
781 {808 {
782 var buf1: [32]u8 = undefined;
783 const value: ?i32 = null;809 const value: ?i32 = null;
784 const result = try bufPrint(buf1[0..], "nullable: {}\n", value);810 try testFmt("nullable: null\n", "nullable: {}\n", value);
785 assert(mem.eql(u8, result, "nullable: null\n"));
786 }811 }
787 {812 {
788 var buf1: [32]u8 = undefined;
789 const value: error!i32 = 1234;813 const value: error!i32 = 1234;
790 const result = try bufPrint(buf1[0..], "error union: {}\n", value);814 try testFmt("error union: 1234\n", "error union: {}\n", value);
791 assert(mem.eql(u8, result, "error union: 1234\n"));
792 }815 }
793 {816 {
794 var buf1: [32]u8 = undefined;
795 const value: error!i32 = error.InvalidChar;817 const value: error!i32 = error.InvalidChar;
796 const result = try bufPrint(buf1[0..], "error union: {}\n", value);818 try testFmt("error union: error.InvalidChar\n", "error union: {}\n", value);
797 assert(mem.eql(u8, result, "error union: error.InvalidChar\n"));
798 }819 }
799 {820 {
800 var buf1: [32]u8 = undefined;
801 const value: u3 = 0b101;821 const value: u3 = 0b101;
802 const result = try bufPrint(buf1[0..], "u3: {}\n", value);822 try testFmt("u3: 5\n", "u3: {}\n", value);
803 assert(mem.eql(u8, result, "u3: 5\n"));
804 }
805 {
806 var buf1: [32]u8 = undefined;
807 const value: usize = 63 * 1024 * 1024;
808 const result = try bufPrint(buf1[0..], "file size: {B}\n", value);
809 assert(mem.eql(u8, result, "file size: 63MB\n"));
810 }823 }
824 try testFmt("file size: 63MiB\n", "file size: {Bi}\n", usize(63 * 1024 * 1024));
825 try testFmt("file size: 66.06MB\n", "file size: {B2}\n", usize(63 * 1024 * 1024));
811 {826 {
812 // Dummy field because of https://github.com/zig-lang/zig/issues/557.827 // Dummy field because of https://github.com/zig-lang/zig/issues/557.
813 const Struct = struct {828 const Struct = struct {
...@@ -1025,6 +1040,20 @@ test "fmt.format" {...@@ -1025,6 +1040,20 @@ test "fmt.format" {
1025 }1040 }
1026}1041}
10271042
1043fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {
1044 var buf: [100]u8 = undefined;
1045 const result = try bufPrint(buf[0..], template, args);
1046 if (mem.eql(u8, result, expected))
1047 return;
1048
1049 std.debug.warn("\n====== expected this output: =========\n");
1050 std.debug.warn("{}", expected);
1051 std.debug.warn("\n======== instead found this: =========\n");
1052 std.debug.warn("{}", result);
1053 std.debug.warn("\n======================================\n");
1054 return error.TestFailed;
1055}
1056
1028pub fn trim(buf: []const u8) []const u8 {1057pub fn trim(buf: []const u8) []const u8 {
1029 var start: usize = 0;1058 var start: usize = 0;
1030 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}1059 while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
std/segmented_list.zig+10-6
...@@ -294,21 +294,25 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type...@@ -294,21 +294,25 @@ pub fn SegmentedList(comptime T: type, comptime prealloc_item_count: usize) type
294294
295 return &it.list.dynamic_segments[it.shelf_index][it.box_index];295 return &it.list.dynamic_segments[it.shelf_index][it.box_index];
296 }296 }
297
298 pub fn set(it: &Iterator, index: usize) void {
299 it.index = index;
300 if (index < prealloc_item_count) return;
301 it.shelf_index = shelfIndex(index);
302 it.box_index = boxIndex(index, it.shelf_index);
303 it.shelf_size = shelfSize(it.shelf_index);
304 }
297 };305 };
298306
299 pub fn iterator(self: &Self, start_index: usize) Iterator {307 pub fn iterator(self: &Self, start_index: usize) Iterator {
300 var it = Iterator{308 var it = Iterator{
301 .list = self,309 .list = self,
302 .index = start_index,310 .index = undefined,
303 .shelf_index = undefined,311 .shelf_index = undefined,
304 .box_index = undefined,312 .box_index = undefined,
305 .shelf_size = undefined,313 .shelf_size = undefined,
306 };314 };
307 if (start_index >= prealloc_item_count) {315 it.set(start_index);
308 it.shelf_index = shelfIndex(start_index);
309 it.box_index = boxIndex(start_index, it.shelf_index);
310 it.shelf_size = shelfSize(it.shelf_index);
311 }
312 return it;316 return it;
313 }317 }
314 };318 };
std/zig/parse.zig+9-1
...@@ -927,6 +927,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -927,6 +927,11 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
927 continue;927 continue;
928 },928 },
929 State.Else => |dest| {929 State.Else => |dest| {
930 const old_index = tok_it.index;
931 var need_index_restore = false;
932 while (try eatLineComment(arena, &tok_it, &tree)) |_| {
933 need_index_restore = true;
934 }
930 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {935 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
931 const node = try arena.construct(ast.Node.Else{936 const node = try arena.construct(ast.Node.Else{
932 .base = ast.Node{ .id = ast.Node.Id.Else },937 .base = ast.Node{ .id = ast.Node.Id.Else },
...@@ -940,6 +945,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -940,6 +945,9 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
940 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });945 try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
941 continue;946 continue;
942 } else {947 } else {
948 if (need_index_restore) {
949 tok_it.set(old_index);
950 }
943 continue;951 continue;
944 }952 }
945 },953 },
...@@ -1297,7 +1305,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {...@@ -1297,7 +1305,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1297 },1305 },
12981306
1299 State.SwitchCaseCommaOrEnd => |list_state| {1307 State.SwitchCaseCommaOrEnd => |list_state| {
1300 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RParen)) {1308 switch (expectCommaOrEnd(&tok_it, &tree, Token.Id.RBrace)) {
1301 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {1309 ExpectCommaOrEndResult.end_token => |maybe_end| if (maybe_end) |end| {
1302 (list_state.ptr).* = end;1310 (list_state.ptr).* = end;
1303 continue;1311 continue;
std/zig/parser_test.zig+92
...@@ -1,3 +1,95 @@...@@ -1,3 +1,95 @@
1test "zig fmt: comment after if before another if" {
2 try testCanonical(
3 \\test "aoeu" {
4 \\ if (x) {
5 \\ foo();
6 \\ }
7 \\ // comment
8 \\ if (x) {
9 \\ bar();
10 \\ }
11 \\}
12 \\
13 );
14}
15
16test "zig fmt: line comment between if block and else keyword" {
17 try testTransform(
18 \\test "aoeu" {
19 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
20 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
21 \\ return Complex(f32).new(y - y, y - y);
22 \\ }
23 \\ // cexp(-inf +- i inf|nan) = 0 + i0
24 \\ else if (hx & 0x80000000 != 0) {
25 \\ return Complex(f32).new(0, 0);
26 \\ }
27 \\ // cexp(+inf +- i inf|nan) = inf + i nan
28 \\ // another comment
29 \\ else {
30 \\ return Complex(f32).new(x, y - y);
31 \\ }
32 \\}
33 ,
34 \\test "aoeu" {
35 \\ // cexp(finite|nan +- i inf|nan) = nan + i nan
36 \\ if ((hx & 0x7fffffff) != 0x7f800000) {
37 \\ return Complex(f32).new(y - y, y - y);
38 \\ } // cexp(-inf +- i inf|nan) = 0 + i0
39 \\ else if (hx & 0x80000000 != 0) {
40 \\ return Complex(f32).new(0, 0);
41 \\ } // cexp(+inf +- i inf|nan) = inf + i nan
42 \\ // another comment
43 \\ else {
44 \\ return Complex(f32).new(x, y - y);
45 \\ }
46 \\}
47 \\
48 );
49}
50
51test "zig fmt: same line comments in expression" {
52 try testCanonical(
53 \\test "aoeu" {
54 \\ const x = ( // a
55 \\ 0 // b
56 \\ ); // c
57 \\}
58 \\
59 );
60}
61
62test "zig fmt: add comma on last switch prong" {
63 try testTransform(
64 \\test "aoeu" {
65 \\switch (self.init_arg_expr) {
66 \\ InitArg.Type => |t| { },
67 \\ InitArg.None,
68 \\ InitArg.Enum => { }
69 \\}
70 \\ switch (self.init_arg_expr) {
71 \\ InitArg.Type => |t| { },
72 \\ InitArg.None,
73 \\ InitArg.Enum => { }//line comment
74 \\ }
75 \\}
76 ,
77 \\test "aoeu" {
78 \\ switch (self.init_arg_expr) {
79 \\ InitArg.Type => |t| {},
80 \\ InitArg.None,
81 \\ InitArg.Enum => {},
82 \\ }
83 \\ switch (self.init_arg_expr) {
84 \\ InitArg.Type => |t| {},
85 \\ InitArg.None,
86 \\ InitArg.Enum => {}, //line comment
87 \\ }
88 \\}
89 \\
90 );
91}
92
1test "zig fmt: same-line doc comment on variable declaration" {93test "zig fmt: same-line doc comment on variable declaration" {
2 try testTransform(94 try testTransform(
3 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space95 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
std/zig/render.zig+45-16
...@@ -81,7 +81,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i...@@ -81,7 +81,7 @@ fn renderTopLevelDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, i
81 }81 }
82 try stream.print("{}: ", tree.tokenSlice(field.name_token));82 try stream.print("{}: ", tree.tokenSlice(field.name_token));
83 try renderExpression(allocator, stream, tree, indent, field.type_expr);83 try renderExpression(allocator, stream, tree, indent, field.type_expr);
84 try renderToken(tree, stream, field.lastToken() + 1, indent, true);84 try renderToken(tree, stream, field.lastToken() + 1, indent, true, true);
85 },85 },
86 ast.Node.Id.UnionTag => {86 ast.Node.Id.UnionTag => {
87 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);87 const tag = @fieldParentPtr(ast.Node.UnionTag, "base", decl);
...@@ -514,9 +514,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -514,9 +514,9 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
514 ast.Node.Id.GroupedExpression => {514 ast.Node.Id.GroupedExpression => {
515 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);515 const grouped_expr = @fieldParentPtr(ast.Node.GroupedExpression, "base", base);
516516
517 try stream.write("(");517 try renderToken(tree, stream, grouped_expr.lparen, indent, false, false);
518 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr);518 try renderExpression(allocator, stream, tree, indent, grouped_expr.expr);
519 try stream.write(")");519 try renderToken(tree, stream, grouped_expr.rparen, indent, false, false);
520 },520 },
521521
522 ast.Node.Id.FieldInitializer => {522 ast.Node.Id.FieldInitializer => {
...@@ -528,7 +528,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -528,7 +528,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
528528
529 ast.Node.Id.IntegerLiteral => {529 ast.Node.Id.IntegerLiteral => {
530 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);530 const integer_literal = @fieldParentPtr(ast.Node.IntegerLiteral, "base", base);
531 try stream.print("{}", tree.tokenSlice(integer_literal.token));531 try renderToken(tree, stream, integer_literal.token, indent, false, false);
532 },532 },
533 ast.Node.Id.FloatLiteral => {533 ast.Node.Id.FloatLiteral => {
534 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);534 const float_literal = @fieldParentPtr(ast.Node.FloatLiteral, "base", base);
...@@ -536,7 +536,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -536,7 +536,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
536 },536 },
537 ast.Node.Id.StringLiteral => {537 ast.Node.Id.StringLiteral => {
538 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);538 const string_literal = @fieldParentPtr(ast.Node.StringLiteral, "base", base);
539 try stream.print("{}", tree.tokenSlice(string_literal.token));539 try renderToken(tree, stream, string_literal.token, indent, false, false);
540 },540 },
541 ast.Node.Id.CharLiteral => {541 ast.Node.Id.CharLiteral => {
542 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);542 const char_literal = @fieldParentPtr(ast.Node.CharLiteral, "base", base);
...@@ -830,7 +830,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -830,7 +830,20 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
830 }830 }
831831
832 try renderExpression(allocator, stream, tree, indent, switch_case.expr);832 try renderExpression(allocator, stream, tree, indent, switch_case.expr);
833 try renderToken(tree, stream, switch_case.lastToken() + 1, indent, true);833 {
834 // Handle missing comma after last switch case
835 var index = switch_case.lastToken() + 1;
836 switch (tree.tokens.at(index).id) {
837 Token.Id.RBrace => {
838 try stream.write(",");
839 },
840 Token.Id.LineComment => {
841 try stream.write(", ");
842 try renderToken(tree, stream, index, indent, true, true);
843 },
844 else => try renderToken(tree, stream, index, indent, true, true),
845 }
846 }
834 },847 },
835 ast.Node.Id.SwitchElse => {848 ast.Node.Id.SwitchElse => {
836 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);849 const switch_else = @fieldParentPtr(ast.Node.SwitchElse, "base", base);
...@@ -838,6 +851,15 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -838,6 +851,15 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
838 },851 },
839 ast.Node.Id.Else => {852 ast.Node.Id.Else => {
840 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);853 const else_node = @fieldParentPtr(ast.Node.Else, "base", base);
854
855 var prev_tok_index = else_node.else_token - 1;
856 while (tree.tokens.at(prev_tok_index).id == Token.Id.LineComment) : (prev_tok_index -= 1) { }
857 prev_tok_index += 1;
858 while (prev_tok_index < else_node.else_token) : (prev_tok_index += 1) {
859 try stream.print("{}\n", tree.tokenSlice(prev_tok_index));
860 try stream.writeByteNTimes(' ', indent);
861 }
862
841 try stream.print("{}", tree.tokenSlice(else_node.else_token));863 try stream.print("{}", tree.tokenSlice(else_node.else_token));
842864
843 const block_body = switch (else_node.body.id) {865 const block_body = switch (else_node.body.id) {
...@@ -959,7 +981,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -959,7 +981,7 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
959 try stream.print("{} (", tree.tokenSlice(if_node.if_token));981 try stream.print("{} (", tree.tokenSlice(if_node.if_token));
960982
961 try renderExpression(allocator, stream, tree, indent, if_node.condition);983 try renderExpression(allocator, stream, tree, indent, if_node.condition);
962 try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false);984 try renderToken(tree, stream, if_node.condition.lastToken() + 1, indent, false, true);
963985
964 if (if_node.payload) |payload| {986 if (if_node.payload) |payload| {
965 try renderExpression(allocator, stream, tree, indent, payload);987 try renderExpression(allocator, stream, tree, indent, payload);
...@@ -1118,11 +1140,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind...@@ -1118,11 +1140,11 @@ fn renderExpression(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, ind
11181140
1119fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void {1141fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void {
1120 if (var_decl.visib_token) |visib_token| {1142 if (var_decl.visib_token) |visib_token| {
1121 try stream.print("{} ", tree.tokenSlice(visib_token));1143 try renderToken(tree, stream, visib_token, indent, false, true);
1122 }1144 }
11231145
1124 if (var_decl.extern_export_token) |extern_export_token| {1146 if (var_decl.extern_export_token) |extern_export_token| {
1125 try stream.print("{} ", tree.tokenSlice(extern_export_token));1147 try renderToken(tree, stream, extern_export_token, indent, false, true);
11261148
1127 if (var_decl.lib_name) |lib_name| {1149 if (var_decl.lib_name) |lib_name| {
1128 try renderExpression(allocator, stream, tree, indent, lib_name);1150 try renderExpression(allocator, stream, tree, indent, lib_name);
...@@ -1131,10 +1153,11 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent...@@ -1131,10 +1153,11 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent
1131 }1153 }
11321154
1133 if (var_decl.comptime_token) |comptime_token| {1155 if (var_decl.comptime_token) |comptime_token| {
1134 try stream.print("{} ", tree.tokenSlice(comptime_token));1156 try renderToken(tree, stream, comptime_token, indent, false, true);
1135 }1157 }
11361158
1137 try stream.print("{} {}", tree.tokenSlice(var_decl.mut_token), tree.tokenSlice(var_decl.name_token));1159 try renderToken(tree, stream, var_decl.mut_token, indent, false, true);
1160 try renderToken(tree, stream, var_decl.name_token, indent, false, false);
11381161
1139 if (var_decl.type_node) |type_node| {1162 if (var_decl.type_node) |type_node| {
1140 try stream.write(": ");1163 try stream.write(": ");
...@@ -1153,14 +1176,14 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent...@@ -1153,14 +1176,14 @@ fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent
1153 try renderExpression(allocator, stream, tree, indent, init_node);1176 try renderExpression(allocator, stream, tree, indent, init_node);
1154 }1177 }
11551178
1156 try renderToken(tree, stream, var_decl.semicolon_token, indent, true);1179 try renderToken(tree, stream, var_decl.semicolon_token, indent, true, false);
1157}1180}
11581181
1159fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {1182fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void {
1160 if (base.requireSemiColon()) {1183 if (base.requireSemiColon()) {
1161 const semicolon_index = base.lastToken() + 1;1184 const semicolon_index = base.lastToken() + 1;
1162 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);1185 assert(tree.tokens.at(semicolon_index).id == Token.Id.Semicolon);
1163 try renderToken(tree, stream, semicolon_index, indent, true);1186 try renderToken(tree, stream, semicolon_index, indent, true, true);
1164 }1187 }
1165}1188}
11661189
...@@ -1195,7 +1218,7 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde...@@ -1195,7 +1218,7 @@ fn renderStatement(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, inde
1195 }1218 }
1196}1219}
11971220
1198fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) (@typeOf(stream).Child.Error || Error)!void {1221fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool, space: bool) (@typeOf(stream).Child.Error || Error)!void {
1199 const token = tree.tokens.at(token_index);1222 const token = tree.tokens.at(token_index);
1200 try stream.write(tree.tokenSlicePtr(token));1223 try stream.write(tree.tokenSlicePtr(token));
12011224
...@@ -1206,13 +1229,19 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent...@@ -1206,13 +1229,19 @@ fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent
1206 try stream.print(" {}", tree.tokenSlicePtr(next_token));1229 try stream.print(" {}", tree.tokenSlicePtr(next_token));
1207 if (!line_break) {1230 if (!line_break) {
1208 try stream.write("\n");1231 try stream.write("\n");
1209 try stream.writeByteNTimes(' ', indent + indent_delta);1232
1233 const after_comment_token = tree.tokens.at(token_index + 2);
1234 const next_line_indent = switch (after_comment_token.id) {
1235 Token.Id.RParen, Token.Id.RBrace, Token.Id.RBracket => indent,
1236 else => indent + indent_delta,
1237 };
1238 try stream.writeByteNTimes(' ', next_line_indent);
1210 return;1239 return;
1211 }1240 }
1212 }1241 }
1213 }1242 }
12141243
1215 if (!line_break) {1244 if (!line_break and space) {
1216 try stream.writeByte(' ');1245 try stream.writeByte(' ');
1217 }1246 }
1218}1247}