| author | |
| committer | |
| log | 99fc2bd4ddbe36994153f6426f0001d338e90bef |
| tree | e5f2be82ac4ae7793212d218ff20422912fd5d32 |
| parent | b73307befb49dd3b131d99ecf1c7f3fb54578ec8 |
| parent | 942d384831196acf24868c32ef84409b05441960 |
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 | }; |
| 31 | 32 | ||
| ... | @@ -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 | } |
| 545 | 564 | ||
| 546 | pub fn formatBytes(value: var, width: ?usize, | 565 | pub fn formatBytes(value: var, width: ?usize, comptime radix: usize, |
| 547 | context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void | 566 | 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 | } |
| 552 | 571 | ||
| 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]; |
| 557 | 580 | ||
| 558 | try formatFloatDecimal(new_value, width, context, Errors, output); | 581 | try formatFloatDecimal(new_value, width, context, Errors, output); |
| 559 | 582 | ||
| 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 | } |
| 565 | 594 | ||
| 566 | pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, | 595 | pub 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" { |
| 773 | 802 | ||
| 774 | test "fmt.format" { | 803 | test "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 | } |
| 1027 | 1042 | ||
| 1043 | fn 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 | |||
| 1028 | pub fn trim(buf: []const u8) []const u8 { | 1057 | pub 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 |
| 294 | 294 | ||
| 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 | }; |
| 298 | 306 | ||
| 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 | }, |
| 1298 | 1306 | ||
| 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 @@ |
| 1 | test "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 | |||
| 16 | test "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 | |||
| 51 | test "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 | |||
| 62 | test "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 | |||
| 1 | test "zig fmt: same-line doc comment on variable declaration" { | 93 | test "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 space | 95 | \\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); |
| 516 | 516 | ||
| 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 | }, |
| 521 | 521 | ||
| 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 |
| 528 | 528 | ||
| 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 | } |
| 831 | 831 | ||
| 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)); |
| 842 | 864 | ||
| 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)); |
| 960 | 982 | ||
| 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); |
| 963 | 985 | ||
| 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 |
| 1118 | 1140 | ||
| 1119 | fn renderVarDecl(allocator: &mem.Allocator, stream: var, tree: &ast.Tree, indent: usize, var_decl: &ast.Node.VarDecl) (@typeOf(stream).Child.Error || Error)!void { | 1141 | fn 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 | } |
| 1123 | 1145 | ||
| 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); |
| 1126 | 1148 | ||
| 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 | } |
| 1132 | 1154 | ||
| 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 | } |
| 1136 | 1158 | ||
| 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); | ||
| 1138 | 1161 | ||
| 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 | } |
| 1155 | 1178 | ||
| 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 | } |
| 1158 | 1181 | ||
| 1159 | fn maybeRenderSemicolon(stream: var, tree: &ast.Tree, indent: usize, base: &ast.Node) (@typeOf(stream).Child.Error || Error)!void { | 1182 | fn 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 | } |
| 1166 | 1189 | ||
| ... | @@ -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 | } |
| 1197 | 1220 | ||
| 1198 | fn renderToken(tree: &ast.Tree, stream: var, token_index: ast.TokenIndex, indent: usize, line_break: bool) (@typeOf(stream).Child.Error || Error)!void { | 1221 | fn 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)); |
| 1201 | 1224 | ||
| ... | @@ -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 | } |
| 1214 | 1243 | ||
| 1215 | if (!line_break) { | 1244 | if (!line_break and space) { |
| 1216 | try stream.writeByte(' '); | 1245 | try stream.writeByte(' '); |
| 1217 | } | 1246 | } |
| 1218 | } | 1247 | } |