authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-16 00:02:26-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-05-16 00:02:26-04:00
log5cfabdd493c6602243f47e24320bae940a3c417a
tree3d8acc6fd643058367a08d44274c8efb46d6829f
parent86a352c45bb654951529660b2e6cbbfa72773170
parent492a214d4c4f4feb15620dfd05230de0086825e5

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


6 files changed, 657 insertions(+), 589 deletions(-)

CMakeLists.txt+1-1
......@@ -196,7 +196,7 @@ else()
196196 if(MSVC)
197197 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -D_CRT_SECURE_NO_WARNINGS /w")
198198 else()
199 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment")
199 set(ZIG_LLD_COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment -Wno-class-memaccess -Wno-unknown-warning-option")
200200 endif()
201201 set_target_properties(embedded_lld_lib PROPERTIES
202202 COMPILE_FLAGS ${ZIG_LLD_COMPILE_FLAGS}
src/ir.cpp+1
......@@ -16555,6 +16555,7 @@ static ConstExprValue *ir_make_type_info_value(IrAnalyze *ira, TypeTableEntry *t
1655516555 {
1655616556 size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index);
1655716557 inner_fields[1].data.x_maybe = create_const_vals(1);
16558 inner_fields[1].data.x_maybe->special = ConstValSpecialStatic;
1655816559 inner_fields[1].data.x_maybe->type = ira->codegen->builtin_types.entry_usize;
1655916560 bigint_init_unsigned(&inner_fields[1].data.x_maybe->data.x_bigint, byte_offset);
1656016561 }
std/fmt/index.zig+59-1
......@@ -25,6 +25,8 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
2525 Character,
2626 Buf,
2727 BufWidth,
28 Bytes,
29 BytesWidth,
2830 };
2931
3032 comptime var start_index = 0;
......@@ -93,6 +95,10 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
9395 '.' => {
9496 state = State.Float;
9597 },
98 'B' => {
99 width = 0;
100 state = State.Bytes;
101 },
96102 else => @compileError("Unknown format character: " ++ []u8{c}),
97103 },
98104 State.Buf => switch (c) {
......@@ -204,6 +210,30 @@ pub fn format(context: var, comptime Errors: type, output: fn(@typeOf(context),
204210 },
205211 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
206212 },
213 State.Bytes => switch (c) {
214 '}' => {
215 try formatBytes(args[next_arg], 0, context, Errors, output);
216 next_arg += 1;
217 state = State.Start;
218 start_index = i + 1;
219 },
220 '0' ... '9' => {
221 width_start = i;
222 state = State.BytesWidth;
223 },
224 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
225 },
226 State.BytesWidth => switch (c) {
227 '}' => {
228 width = comptime (parseUnsigned(usize, fmt[width_start..i], 10) catch unreachable);
229 try formatBytes(args[next_arg], width, context, Errors, output);
230 next_arg += 1;
231 state = State.Start;
232 start_index = i + 1;
233 },
234 '0' ... '9' => {},
235 else => @compileError("Unexpected character in format string: " ++ []u8{c}),
236 },
207237 }
208238 }
209239 comptime {
......@@ -513,7 +543,29 @@ pub fn formatFloatDecimal(value: var, maybe_precision: ?usize, context: var, com
513543 }
514544}
515545
516pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize, context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8) Errors!void) Errors!void {
546pub fn formatBytes(value: var, width: ?usize,
547 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
548{
549 if (value == 0) {
550 return output(context, "0B");
551 }
552
553 const mags = " KMGTPEZY";
554 const magnitude = math.min(math.log2(value) / 10, mags.len - 1);
555 const new_value = f64(value) / math.pow(f64, 1024, f64(magnitude));
556 const suffix = mags[magnitude];
557
558 try formatFloatDecimal(new_value, width, context, Errors, output);
559
560 if (suffix != ' ') {
561 try output(context, (&suffix)[0..1]);
562 }
563 return output(context, "B");
564}
565
566pub fn formatInt(value: var, base: u8, uppercase: bool, width: usize,
567 context: var, comptime Errors: type, output: fn(@typeOf(context), []const u8)Errors!void) Errors!void
568{
517569 if (@typeOf(value).is_signed) {
518570 return formatIntSigned(value, base, uppercase, width, context, Errors, output);
519571 } else {
......@@ -750,6 +802,12 @@ test "fmt.format" {
750802 const result = try bufPrint(buf1[0..], "u3: {}\n", value);
751803 assert(mem.eql(u8, result, "u3: 5\n"));
752804 }
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 }
753811 {
754812 // Dummy field because of https://github.com/zig-lang/zig/issues/557.
755813 const Struct = struct {
std/zig/parse.zig+405-445
......@@ -17,15 +17,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
1717 defer stack.deinit();
1818
1919 const arena = &tree_arena.allocator;
20 const root_node = try createNode(arena, ast.Node.Root,
21 ast.Node.Root {
22 .base = undefined,
23 .decls = ast.Node.Root.DeclList.init(arena),
24 .doc_comments = null,
25 // initialized when we get the eof token
26 .eof_token = undefined,
27 }
28 );
20 const root_node = try arena.construct(ast.Node.Root {
21 .base = ast.Node { .id = ast.Node.Id.Root },
22 .decls = ast.Node.Root.DeclList.init(arena),
23 .doc_comments = null,
24 // initialized when we get the eof token
25 .eof_token = undefined,
26 });
2927
3028 var tree = ast.Tree {
3129 .source = source,
......@@ -113,15 +111,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
113111 continue;
114112 },
115113 Token.Id.Keyword_comptime => {
116 const block = try createNode(arena, ast.Node.Block,
117 ast.Node.Block {
118 .base = undefined,
119 .label = null,
120 .lbrace = undefined,
121 .statements = ast.Node.Block.StatementList.init(arena),
122 .rbrace = undefined,
123 }
124 );
114 const block = try arena.construct(ast.Node.Block {
115 .base = ast.Node {.id = ast.Node.Id.Block },
116 .label = null,
117 .lbrace = undefined,
118 .statements = ast.Node.Block.StatementList.init(arena),
119 .rbrace = undefined,
120 });
125121 const node = try arena.construct(ast.Node.Comptime {
126122 .base = ast.Node {
127123 .id = ast.Node.Id.Comptime,
......@@ -312,14 +308,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
312308 continue;
313309 },
314310 Token.Id.Keyword_async => {
315 const async_node = try createNode(arena, ast.Node.AsyncAttribute,
316 ast.Node.AsyncAttribute {
317 .base = undefined,
318 .async_token = token_index,
319 .allocator_type = null,
320 .rangle_bracket = null,
321 }
322 );
311 const async_node = try arena.construct(ast.Node.AsyncAttribute {
312 .base = ast.Node {.id = ast.Node.Id.AsyncAttribute },
313 .async_token = token_index,
314 .allocator_type = null,
315 .rangle_bracket = null,
316 });
323317 fn_proto.async_attr = async_node;
324318
325319 try stack.append(State {
......@@ -396,27 +390,26 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
396390 const token = nextToken(&tok_it, &tree);
397391 const token_index = token.index;
398392 const token_ptr = token.ptr;
399 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.ContainerDecl,
400 ast.Node.ContainerDecl {
401 .base = undefined,
402 .ltoken = ctx.ltoken,
403 .layout = ctx.layout,
404 .kind = switch (token_ptr.id) {
405 Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct,
406 Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union,
407 Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum,
408 else => {
409 *(try tree.errors.addOne()) = Error {
410 .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index },
411 };
412 return tree;
413 },
393 const node = try arena.construct(ast.Node.ContainerDecl {
394 .base = ast.Node {.id = ast.Node.Id.ContainerDecl },
395 .ltoken = ctx.ltoken,
396 .layout = ctx.layout,
397 .kind = switch (token_ptr.id) {
398 Token.Id.Keyword_struct => ast.Node.ContainerDecl.Kind.Struct,
399 Token.Id.Keyword_union => ast.Node.ContainerDecl.Kind.Union,
400 Token.Id.Keyword_enum => ast.Node.ContainerDecl.Kind.Enum,
401 else => {
402 *(try tree.errors.addOne()) = Error {
403 .ExpectedAggregateKw = Error.ExpectedAggregateKw { .token = token_index },
404 };
405 return tree;
414406 },
415 .init_arg_expr = ast.Node.ContainerDecl.InitArg.None,
416 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
417 .rbrace_token = undefined,
418 }
419 );
407 },
408 .init_arg_expr = ast.Node.ContainerDecl.InitArg.None,
409 .fields_and_decls = ast.Node.ContainerDecl.DeclList.init(arena),
410 .rbrace_token = undefined,
411 });
412 ctx.opt_ctx.store(&node.base);
420413
421414 stack.append(State { .ContainerDecl = node }) catch unreachable;
422415 try stack.append(State { .ExpectToken = Token.Id.LBrace });
......@@ -647,12 +640,7 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
647640 switch (token_ptr.id) {
648641 Token.Id.Equal => {
649642 var_decl.eq_token = token_index;
650 stack.append(State {
651 .ExpectTokenSave = ExpectTokenSave {
652 .id = Token.Id.Semicolon,
653 .ptr = &var_decl.semicolon_token,
654 },
655 }) catch unreachable;
643 stack.append(State { .VarDeclSemiColon = var_decl }) catch unreachable;
656644 try stack.append(State { .Expression = OptionalCtx { .RequiredNull = &var_decl.init_node } });
657645 continue;
658646 },
......@@ -669,6 +657,30 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
669657 }
670658 },
671659
660 State.VarDeclSemiColon => |var_decl| {
661 const semicolon_token = nextToken(&tok_it, &tree);
662
663 if (semicolon_token.ptr.id != Token.Id.Semicolon) {
664 *(try tree.errors.addOne()) = Error {
665 .ExpectedToken = Error.ExpectedToken {
666 .token = semicolon_token.index,
667 .expected_id = Token.Id.Semicolon,
668 },
669 };
670 return tree;
671 }
672
673 var_decl.semicolon_token = semicolon_token.index;
674
675 if (eatToken(&tok_it, &tree, Token.Id.DocComment)) |doc_comment_token| {
676 const loc = tree.tokenLocation(semicolon_token.ptr.end, doc_comment_token);
677 if (loc.line == 0) {
678 try pushDocComment(arena, doc_comment_token, &var_decl.doc_comments);
679 } else {
680 putBackToken(&tok_it, &tree);
681 }
682 }
683 },
672684
673685 State.FnDef => |fn_proto| {
674686 const token = nextToken(&tok_it, &tree);
......@@ -844,15 +856,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
844856 const token_ptr = token.ptr;
845857 switch (token_ptr.id) {
846858 Token.Id.LBrace => {
847 const block = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.Block,
848 ast.Node.Block {
849 .base = undefined,
850 .label = ctx.label,
851 .lbrace = token_index,
852 .statements = ast.Node.Block.StatementList.init(arena),
853 .rbrace = undefined,
854 }
855 );
859 const block = try arena.construct(ast.Node.Block {
860 .base = ast.Node {.id = ast.Node.Id.Block},
861 .label = ctx.label,
862 .lbrace = token_index,
863 .statements = ast.Node.Block.StatementList.init(arena),
864 .rbrace = undefined,
865 });
866 ctx.opt_ctx.store(&block.base);
856867 stack.append(State { .Block = block }) catch unreachable;
857868 continue;
858869 },
......@@ -957,19 +968,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
957968 }
958969 },
959970 State.While => |ctx| {
960 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.While,
961 ast.Node.While {
962 .base = undefined,
963 .label = ctx.label,
964 .inline_token = ctx.inline_token,
965 .while_token = ctx.loop_token,
966 .condition = undefined,
967 .payload = null,
968 .continue_expr = null,
969 .body = undefined,
970 .@"else" = null,
971 }
972 );
971 const node = try arena.construct(ast.Node.While {
972 .base = ast.Node {.id = ast.Node.Id.While },
973 .label = ctx.label,
974 .inline_token = ctx.inline_token,
975 .while_token = ctx.loop_token,
976 .condition = undefined,
977 .payload = null,
978 .continue_expr = null,
979 .body = undefined,
980 .@"else" = null,
981 });
982 ctx.opt_ctx.store(&node.base);
973983 stack.append(State { .Else = &node.@"else" }) catch unreachable;
974984 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
975985 try stack.append(State { .WhileContinueExpr = &node.continue_expr });
......@@ -987,18 +997,17 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
987997 continue;
988998 },
989999 State.For => |ctx| {
990 const node = try createToCtxNode(arena, ctx.opt_ctx, ast.Node.For,
991 ast.Node.For {
992 .base = undefined,
993 .label = ctx.label,
994 .inline_token = ctx.inline_token,
995 .for_token = ctx.loop_token,
996 .array_expr = undefined,
997 .payload = null,
998 .body = undefined,
999 .@"else" = null,
1000 }
1001 );
1000 const node = try arena.construct(ast.Node.For {
1001 .base = ast.Node {.id = ast.Node.Id.For },
1002 .label = ctx.label,
1003 .inline_token = ctx.inline_token,
1004 .for_token = ctx.loop_token,
1005 .array_expr = undefined,
1006 .payload = null,
1007 .body = undefined,
1008 .@"else" = null,
1009 });
1010 ctx.opt_ctx.store(&node.base);
10021011 stack.append(State { .Else = &node.@"else" }) catch unreachable;
10031012 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
10041013 try stack.append(State { .PointerIndexPayload = OptionalCtx { .Optional = &node.payload } });
......@@ -1009,14 +1018,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
10091018 },
10101019 State.Else => |dest| {
10111020 if (eatToken(&tok_it, &tree, Token.Id.Keyword_else)) |else_token| {
1012 const node = try createNode(arena, ast.Node.Else,
1013 ast.Node.Else {
1014 .base = undefined,
1015 .else_token = else_token,
1016 .payload = null,
1017 .body = undefined,
1018 }
1019 );
1021 const node = try arena.construct(ast.Node.Else {
1022 .base = ast.Node {.id = ast.Node.Id.Else },
1023 .else_token = else_token,
1024 .payload = null,
1025 .body = undefined,
1026 });
10201027 *dest = node;
10211028
10221029 stack.append(State { .Expression = OptionalCtx { .Required = &node.body } }) catch unreachable;
......@@ -1170,14 +1177,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
11701177 continue;
11711178 }
11721179
1173 const node = try createNode(arena, ast.Node.AsmOutput,
1174 ast.Node.AsmOutput {
1175 .base = undefined,
1176 .symbolic_name = undefined,
1177 .constraint = undefined,
1178 .kind = undefined,
1179 }
1180 );
1180 const node = try arena.construct(ast.Node.AsmOutput {
1181 .base = ast.Node {.id = ast.Node.Id.AsmOutput },
1182 .symbolic_name = undefined,
1183 .constraint = undefined,
1184 .kind = undefined,
1185 });
11811186 try items.push(node);
11821187
11831188 stack.append(State { .AsmOutputItems = items }) catch unreachable;
......@@ -1223,14 +1228,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
12231228 continue;
12241229 }
12251230
1226 const node = try createNode(arena, ast.Node.AsmInput,
1227 ast.Node.AsmInput {
1228 .base = undefined,
1229 .symbolic_name = undefined,
1230 .constraint = undefined,
1231 .expr = undefined,
1232 }
1233 );
1231 const node = try arena.construct(ast.Node.AsmInput {
1232 .base = ast.Node {.id = ast.Node.Id.AsmInput },
1233 .symbolic_name = undefined,
1234 .constraint = undefined,
1235 .expr = undefined,
1236 });
12341237 try items.push(node);
12351238
12361239 stack.append(State { .AsmInputItems = items }) catch unreachable;
......@@ -1668,14 +1671,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
16681671 continue;
16691672 }
16701673
1671 const node = try createToCtxNode(arena, opt_ctx, ast.Node.Payload,
1672 ast.Node.Payload {
1673 .base = undefined,
1674 .lpipe = token_index,
1675 .error_symbol = undefined,
1676 .rpipe = undefined
1677 }
1678 );
1674 const node = try arena.construct(ast.Node.Payload {
1675 .base = ast.Node {.id = ast.Node.Id.Payload },
1676 .lpipe = token_index,
1677 .error_symbol = undefined,
1678 .rpipe = undefined
1679 });
1680 opt_ctx.store(&node.base);
16791681
16801682 stack.append(State {
16811683 .ExpectTokenSave = ExpectTokenSave {
......@@ -1705,15 +1707,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
17051707 continue;
17061708 }
17071709
1708 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerPayload,
1709 ast.Node.PointerPayload {
1710 .base = undefined,
1711 .lpipe = token_index,
1712 .ptr_token = null,
1713 .value_symbol = undefined,
1714 .rpipe = undefined
1715 }
1716 );
1710 const node = try arena.construct(ast.Node.PointerPayload {
1711 .base = ast.Node {.id = ast.Node.Id.PointerPayload },
1712 .lpipe = token_index,
1713 .ptr_token = null,
1714 .value_symbol = undefined,
1715 .rpipe = undefined
1716 });
1717 opt_ctx.store(&node.base);
17171718
17181719 try stack.append(State {
17191720 .ExpectTokenSave = ExpectTokenSave {
......@@ -1749,16 +1750,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
17491750 continue;
17501751 }
17511752
1752 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PointerIndexPayload,
1753 ast.Node.PointerIndexPayload {
1754 .base = undefined,
1755 .lpipe = token_index,
1756 .ptr_token = null,
1757 .value_symbol = undefined,
1758 .index_symbol = null,
1759 .rpipe = undefined
1760 }
1761 );
1753 const node = try arena.construct(ast.Node.PointerIndexPayload {
1754 .base = ast.Node {.id = ast.Node.Id.PointerIndexPayload },
1755 .lpipe = token_index,
1756 .ptr_token = null,
1757 .value_symbol = undefined,
1758 .index_symbol = null,
1759 .rpipe = undefined
1760 });
1761 opt_ctx.store(&node.base);
17621762
17631763 stack.append(State {
17641764 .ExpectTokenSave = ExpectTokenSave {
......@@ -1785,14 +1785,13 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
17851785 const token_ptr = token.ptr;
17861786 switch (token_ptr.id) {
17871787 Token.Id.Keyword_return, Token.Id.Keyword_break, Token.Id.Keyword_continue => {
1788 const node = try createToCtxNode(arena, opt_ctx, ast.Node.ControlFlowExpression,
1789 ast.Node.ControlFlowExpression {
1790 .base = undefined,
1791 .ltoken = token_index,
1792 .kind = undefined,
1793 .rhs = null,
1794 }
1795 );
1788 const node = try arena.construct(ast.Node.ControlFlowExpression {
1789 .base = ast.Node {.id = ast.Node.Id.ControlFlowExpression },
1790 .ltoken = token_index,
1791 .kind = undefined,
1792 .rhs = null,
1793 });
1794 opt_ctx.store(&node.base);
17961795
17971796 stack.append(State { .Expression = OptionalCtx { .Optional = &node.rhs } }) catch unreachable;
17981797
......@@ -1815,19 +1814,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
18151814 continue;
18161815 },
18171816 Token.Id.Keyword_try, Token.Id.Keyword_cancel, Token.Id.Keyword_resume => {
1818 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
1819 ast.Node.PrefixOp {
1820 .base = undefined,
1821 .op_token = token_index,
1822 .op = switch (token_ptr.id) {
1823 Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} },
1824 Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} },
1825 Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} },
1826 else => unreachable,
1827 },
1828 .rhs = undefined,
1829 }
1830 );
1817 const node = try arena.construct(ast.Node.PrefixOp {
1818 .base = ast.Node {.id = ast.Node.Id.PrefixOp },
1819 .op_token = token_index,
1820 .op = switch (token_ptr.id) {
1821 Token.Id.Keyword_try => ast.Node.PrefixOp.Op { .Try = void{} },
1822 Token.Id.Keyword_cancel => ast.Node.PrefixOp.Op { .Cancel = void{} },
1823 Token.Id.Keyword_resume => ast.Node.PrefixOp.Op { .Resume = void{} },
1824 else => unreachable,
1825 },
1826 .rhs = undefined,
1827 });
1828 opt_ctx.store(&node.base);
18311829
18321830 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
18331831 continue;
......@@ -1850,15 +1848,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
18501848 const lhs = opt_ctx.get() ?? continue;
18511849
18521850 if (eatToken(&tok_it, &tree, Token.Id.Ellipsis3)) |ellipsis3| {
1853 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1854 ast.Node.InfixOp {
1855 .base = undefined,
1856 .lhs = lhs,
1857 .op_token = ellipsis3,
1858 .op = ast.Node.InfixOp.Op.Range,
1859 .rhs = undefined,
1860 }
1861 );
1851 const node = try arena.construct(ast.Node.InfixOp {
1852 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1853 .lhs = lhs,
1854 .op_token = ellipsis3,
1855 .op = ast.Node.InfixOp.Op.Range,
1856 .rhs = undefined,
1857 });
1858 opt_ctx.store(&node.base);
18621859 stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } }) catch unreachable;
18631860 continue;
18641861 }
......@@ -1876,15 +1873,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
18761873 const token_index = token.index;
18771874 const token_ptr = token.ptr;
18781875 if (tokenIdToAssignment(token_ptr.id)) |ass_id| {
1879 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1880 ast.Node.InfixOp {
1881 .base = undefined,
1882 .lhs = lhs,
1883 .op_token = token_index,
1884 .op = ass_id,
1885 .rhs = undefined,
1886 }
1887 );
1876 const node = try arena.construct(ast.Node.InfixOp {
1877 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1878 .lhs = lhs,
1879 .op_token = token_index,
1880 .op = ass_id,
1881 .rhs = undefined,
1882 });
1883 opt_ctx.store(&node.base);
18881884 stack.append(State { .AssignmentExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
18891885 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
18901886 continue;
......@@ -1907,15 +1903,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19071903 const token_index = token.index;
19081904 const token_ptr = token.ptr;
19091905 if (tokenIdToUnwrapExpr(token_ptr.id)) |unwrap_id| {
1910 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1911 ast.Node.InfixOp {
1912 .base = undefined,
1913 .lhs = lhs,
1914 .op_token = token_index,
1915 .op = unwrap_id,
1916 .rhs = undefined,
1917 }
1918 );
1906 const node = try arena.construct(ast.Node.InfixOp {
1907 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1908 .lhs = lhs,
1909 .op_token = token_index,
1910 .op = unwrap_id,
1911 .rhs = undefined,
1912 });
1913 opt_ctx.store(&node.base);
19191914
19201915 stack.append(State { .UnwrapExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19211916 try stack.append(State { .Expression = OptionalCtx { .Required = &node.rhs } });
......@@ -1940,15 +1935,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19401935 const lhs = opt_ctx.get() ?? continue;
19411936
19421937 if (eatToken(&tok_it, &tree, Token.Id.Keyword_or)) |or_token| {
1943 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1944 ast.Node.InfixOp {
1945 .base = undefined,
1946 .lhs = lhs,
1947 .op_token = or_token,
1948 .op = ast.Node.InfixOp.Op.BoolOr,
1949 .rhs = undefined,
1950 }
1951 );
1938 const node = try arena.construct(ast.Node.InfixOp {
1939 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1940 .lhs = lhs,
1941 .op_token = or_token,
1942 .op = ast.Node.InfixOp.Op.BoolOr,
1943 .rhs = undefined,
1944 });
1945 opt_ctx.store(&node.base);
19521946 stack.append(State { .BoolOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19531947 try stack.append(State { .BoolAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
19541948 continue;
......@@ -1965,15 +1959,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19651959 const lhs = opt_ctx.get() ?? continue;
19661960
19671961 if (eatToken(&tok_it, &tree, Token.Id.Keyword_and)) |and_token| {
1968 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1969 ast.Node.InfixOp {
1970 .base = undefined,
1971 .lhs = lhs,
1972 .op_token = and_token,
1973 .op = ast.Node.InfixOp.Op.BoolAnd,
1974 .rhs = undefined,
1975 }
1976 );
1962 const node = try arena.construct(ast.Node.InfixOp {
1963 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1964 .lhs = lhs,
1965 .op_token = and_token,
1966 .op = ast.Node.InfixOp.Op.BoolAnd,
1967 .rhs = undefined,
1968 });
1969 opt_ctx.store(&node.base);
19771970 stack.append(State { .BoolAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
19781971 try stack.append(State { .ComparisonExpressionBegin = OptionalCtx { .Required = &node.rhs } });
19791972 continue;
......@@ -1993,15 +1986,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
19931986 const token_index = token.index;
19941987 const token_ptr = token.ptr;
19951988 if (tokenIdToComparison(token_ptr.id)) |comp_id| {
1996 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
1997 ast.Node.InfixOp {
1998 .base = undefined,
1999 .lhs = lhs,
2000 .op_token = token_index,
2001 .op = comp_id,
2002 .rhs = undefined,
2003 }
2004 );
1989 const node = try arena.construct(ast.Node.InfixOp {
1990 .base = ast.Node {.id = ast.Node.Id.InfixOp },
1991 .lhs = lhs,
1992 .op_token = token_index,
1993 .op = comp_id,
1994 .rhs = undefined,
1995 });
1996 opt_ctx.store(&node.base);
20051997 stack.append(State { .ComparisonExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20061998 try stack.append(State { .BinaryOrExpressionBegin = OptionalCtx { .Required = &node.rhs } });
20071999 continue;
......@@ -2021,15 +2013,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20212013 const lhs = opt_ctx.get() ?? continue;
20222014
20232015 if (eatToken(&tok_it, &tree, Token.Id.Pipe)) |pipe| {
2024 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2025 ast.Node.InfixOp {
2026 .base = undefined,
2027 .lhs = lhs,
2028 .op_token = pipe,
2029 .op = ast.Node.InfixOp.Op.BitOr,
2030 .rhs = undefined,
2031 }
2032 );
2016 const node = try arena.construct(ast.Node.InfixOp {
2017 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2018 .lhs = lhs,
2019 .op_token = pipe,
2020 .op = ast.Node.InfixOp.Op.BitOr,
2021 .rhs = undefined,
2022 });
2023 opt_ctx.store(&node.base);
20332024 stack.append(State { .BinaryOrExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20342025 try stack.append(State { .BinaryXorExpressionBegin = OptionalCtx { .Required = &node.rhs } });
20352026 continue;
......@@ -2046,15 +2037,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20462037 const lhs = opt_ctx.get() ?? continue;
20472038
20482039 if (eatToken(&tok_it, &tree, Token.Id.Caret)) |caret| {
2049 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2050 ast.Node.InfixOp {
2051 .base = undefined,
2052 .lhs = lhs,
2053 .op_token = caret,
2054 .op = ast.Node.InfixOp.Op.BitXor,
2055 .rhs = undefined,
2056 }
2057 );
2040 const node = try arena.construct(ast.Node.InfixOp {
2041 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2042 .lhs = lhs,
2043 .op_token = caret,
2044 .op = ast.Node.InfixOp.Op.BitXor,
2045 .rhs = undefined,
2046 });
2047 opt_ctx.store(&node.base);
20582048 stack.append(State { .BinaryXorExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20592049 try stack.append(State { .BinaryAndExpressionBegin = OptionalCtx { .Required = &node.rhs } });
20602050 continue;
......@@ -2071,15 +2061,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20712061 const lhs = opt_ctx.get() ?? continue;
20722062
20732063 if (eatToken(&tok_it, &tree, Token.Id.Ampersand)) |ampersand| {
2074 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2075 ast.Node.InfixOp {
2076 .base = undefined,
2077 .lhs = lhs,
2078 .op_token = ampersand,
2079 .op = ast.Node.InfixOp.Op.BitAnd,
2080 .rhs = undefined,
2081 }
2082 );
2064 const node = try arena.construct(ast.Node.InfixOp {
2065 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2066 .lhs = lhs,
2067 .op_token = ampersand,
2068 .op = ast.Node.InfixOp.Op.BitAnd,
2069 .rhs = undefined,
2070 });
2071 opt_ctx.store(&node.base);
20832072 stack.append(State { .BinaryAndExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
20842073 try stack.append(State { .BitShiftExpressionBegin = OptionalCtx { .Required = &node.rhs } });
20852074 continue;
......@@ -2099,15 +2088,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
20992088 const token_index = token.index;
21002089 const token_ptr = token.ptr;
21012090 if (tokenIdToBitShift(token_ptr.id)) |bitshift_id| {
2102 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2103 ast.Node.InfixOp {
2104 .base = undefined,
2105 .lhs = lhs,
2106 .op_token = token_index,
2107 .op = bitshift_id,
2108 .rhs = undefined,
2109 }
2110 );
2091 const node = try arena.construct(ast.Node.InfixOp {
2092 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2093 .lhs = lhs,
2094 .op_token = token_index,
2095 .op = bitshift_id,
2096 .rhs = undefined,
2097 });
2098 opt_ctx.store(&node.base);
21112099 stack.append(State { .BitShiftExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21122100 try stack.append(State { .AdditionExpressionBegin = OptionalCtx { .Required = &node.rhs } });
21132101 continue;
......@@ -2130,15 +2118,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21302118 const token_index = token.index;
21312119 const token_ptr = token.ptr;
21322120 if (tokenIdToAddition(token_ptr.id)) |add_id| {
2133 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2134 ast.Node.InfixOp {
2135 .base = undefined,
2136 .lhs = lhs,
2137 .op_token = token_index,
2138 .op = add_id,
2139 .rhs = undefined,
2140 }
2141 );
2121 const node = try arena.construct(ast.Node.InfixOp {
2122 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2123 .lhs = lhs,
2124 .op_token = token_index,
2125 .op = add_id,
2126 .rhs = undefined,
2127 });
2128 opt_ctx.store(&node.base);
21422129 stack.append(State { .AdditionExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21432130 try stack.append(State { .MultiplyExpressionBegin = OptionalCtx { .Required = &node.rhs } });
21442131 continue;
......@@ -2161,15 +2148,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
21612148 const token_index = token.index;
21622149 const token_ptr = token.ptr;
21632150 if (tokenIdToMultiply(token_ptr.id)) |mult_id| {
2164 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2165 ast.Node.InfixOp {
2166 .base = undefined,
2167 .lhs = lhs,
2168 .op_token = token_index,
2169 .op = mult_id,
2170 .rhs = undefined,
2171 }
2172 );
2151 const node = try arena.construct(ast.Node.InfixOp {
2152 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2153 .lhs = lhs,
2154 .op_token = token_index,
2155 .op = mult_id,
2156 .rhs = undefined,
2157 });
2158 opt_ctx.store(&node.base);
21732159 stack.append(State { .MultiplyExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
21742160 try stack.append(State { .CurlySuffixExpressionBegin = OptionalCtx { .Required = &node.rhs } });
21752161 continue;
......@@ -2211,16 +2197,15 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
22112197 continue;
22122198 }
22132199
2214 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2215 ast.Node.SuffixOp {
2216 .base = undefined,
2217 .lhs = lhs,
2218 .op = ast.Node.SuffixOp.Op {
2219 .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena),
2220 },
2221 .rtoken = undefined,
2222 }
2223 );
2200 const node = try arena.construct(ast.Node.SuffixOp {
2201 .base = ast.Node {.id = ast.Node.Id.SuffixOp },
2202 .lhs = lhs,
2203 .op = ast.Node.SuffixOp.Op {
2204 .ArrayInitializer = ast.Node.SuffixOp.Op.InitList.init(arena),
2205 },
2206 .rtoken = undefined,
2207 });
2208 opt_ctx.store(&node.base);
22242209 stack.append(State { .CurlySuffixExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
22252210 try stack.append(State { .IfToken = Token.Id.LBrace });
22262211 try stack.append(State {
......@@ -2243,15 +2228,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
22432228 const lhs = opt_ctx.get() ?? continue;
22442229
22452230 if (eatToken(&tok_it, &tree, Token.Id.Bang)) |bang| {
2246 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2247 ast.Node.InfixOp {
2248 .base = undefined,
2249 .lhs = lhs,
2250 .op_token = bang,
2251 .op = ast.Node.InfixOp.Op.ErrorUnion,
2252 .rhs = undefined,
2253 }
2254 );
2231 const node = try arena.construct(ast.Node.InfixOp {
2232 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2233 .lhs = lhs,
2234 .op_token = bang,
2235 .op = ast.Node.InfixOp.Op.ErrorUnion,
2236 .rhs = undefined,
2237 });
2238 opt_ctx.store(&node.base);
22552239 stack.append(State { .TypeExprEnd = opt_ctx.toRequired() }) catch unreachable;
22562240 try stack.append(State { .PrefixOpExpression = OptionalCtx { .Required = &node.rhs } });
22572241 continue;
......@@ -2263,25 +2247,22 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
22632247 const token_index = token.index;
22642248 const token_ptr = token.ptr;
22652249 if (tokenIdToPrefixOp(token_ptr.id)) |prefix_id| {
2266 var node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
2267 ast.Node.PrefixOp {
2268 .base = undefined,
2269 .op_token = token_index,
2270 .op = prefix_id,
2271 .rhs = undefined,
2272 }
2273 );
2250 var node = try arena.construct(ast.Node.PrefixOp {
2251 .base = ast.Node {.id = ast.Node.Id.PrefixOp },
2252 .op_token = token_index,
2253 .op = prefix_id,
2254 .rhs = undefined,
2255 });
2256 opt_ctx.store(&node.base);
22742257
22752258 // Treat '**' token as two derefs
22762259 if (token_ptr.id == Token.Id.AsteriskAsterisk) {
2277 const child = try createNode(arena, ast.Node.PrefixOp,
2278 ast.Node.PrefixOp {
2279 .base = undefined,
2280 .op_token = token_index,
2281 .op = prefix_id,
2282 .rhs = undefined,
2283 }
2284 );
2260 const child = try arena.construct(ast.Node.PrefixOp {
2261 .base = ast.Node {.id = ast.Node.Id.PrefixOp},
2262 .op_token = token_index,
2263 .op = prefix_id,
2264 .rhs = undefined,
2265 });
22852266 node.rhs = &child.base;
22862267 node = child;
22872268 }
......@@ -2300,14 +2281,12 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
23002281
23012282 State.SuffixOpExpressionBegin => |opt_ctx| {
23022283 if (eatToken(&tok_it, &tree, Token.Id.Keyword_async)) |async_token| {
2303 const async_node = try createNode(arena, ast.Node.AsyncAttribute,
2304 ast.Node.AsyncAttribute {
2305 .base = undefined,
2306 .async_token = async_token,
2307 .allocator_type = null,
2308 .rangle_bracket = null,
2309 }
2310 );
2284 const async_node = try arena.construct(ast.Node.AsyncAttribute {
2285 .base = ast.Node {.id = ast.Node.Id.AsyncAttribute},
2286 .async_token = async_token,
2287 .allocator_type = null,
2288 .rangle_bracket = null,
2289 });
23112290 stack.append(State {
23122291 .AsyncEnd = AsyncEndCtx {
23132292 .ctx = opt_ctx,
......@@ -2333,19 +2312,19 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
23332312 const token_ptr = token.ptr;
23342313 switch (token_ptr.id) {
23352314 Token.Id.LParen => {
2336 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2337 ast.Node.SuffixOp {
2338 .base = undefined,
2339 .lhs = lhs,
2340 .op = ast.Node.SuffixOp.Op {
2341 .Call = ast.Node.SuffixOp.Op.Call {
2342 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena),
2343 .async_attr = null,
2344 }
2345 },
2346 .rtoken = undefined,
2347 }
2348 );
2315 const node = try arena.construct(ast.Node.SuffixOp {
2316 .base = ast.Node {.id = ast.Node.Id.SuffixOp },
2317 .lhs = lhs,
2318 .op = ast.Node.SuffixOp.Op {
2319 .Call = ast.Node.SuffixOp.Op.Call {
2320 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(arena),
2321 .async_attr = null,
2322 }
2323 },
2324 .rtoken = undefined,
2325 });
2326 opt_ctx.store(&node.base);
2327
23492328 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
23502329 try stack.append(State {
23512330 .ExprListItemOrEnd = ExprListCtx {
......@@ -2357,31 +2336,31 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
23572336 continue;
23582337 },
23592338 Token.Id.LBracket => {
2360 const node = try createToCtxNode(arena, opt_ctx, ast.Node.SuffixOp,
2361 ast.Node.SuffixOp {
2362 .base = undefined,
2363 .lhs = lhs,
2364 .op = ast.Node.SuffixOp.Op {
2365 .ArrayAccess = undefined,
2366 },
2367 .rtoken = undefined
2368 }
2369 );
2339 const node = try arena.construct(ast.Node.SuffixOp {
2340 .base = ast.Node {.id = ast.Node.Id.SuffixOp },
2341 .lhs = lhs,
2342 .op = ast.Node.SuffixOp.Op {
2343 .ArrayAccess = undefined,
2344 },
2345 .rtoken = undefined
2346 });
2347 opt_ctx.store(&node.base);
2348
23702349 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
23712350 try stack.append(State { .SliceOrArrayAccess = node });
23722351 try stack.append(State { .Expression = OptionalCtx { .Required = &node.op.ArrayAccess }});
23732352 continue;
23742353 },
23752354 Token.Id.Period => {
2376 const node = try createToCtxNode(arena, opt_ctx, ast.Node.InfixOp,
2377 ast.Node.InfixOp {
2378 .base = undefined,
2379 .lhs = lhs,
2380 .op_token = token_index,
2381 .op = ast.Node.InfixOp.Op.Period,
2382 .rhs = undefined,
2383 }
2384 );
2355 const node = try arena.construct(ast.Node.InfixOp {
2356 .base = ast.Node {.id = ast.Node.Id.InfixOp },
2357 .lhs = lhs,
2358 .op_token = token_index,
2359 .op = ast.Node.InfixOp.Op.Period,
2360 .rhs = undefined,
2361 });
2362 opt_ctx.store(&node.base);
2363
23852364 stack.append(State { .SuffixOpExpressionEnd = opt_ctx.toRequired() }) catch unreachable;
23862365 try stack.append(State { .Identifier = OptionalCtx { .Required = &node.rhs } });
23872366 continue;
......@@ -2461,14 +2440,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24612440 continue;
24622441 },
24632442 Token.Id.LParen => {
2464 const node = try createToCtxNode(arena, opt_ctx, ast.Node.GroupedExpression,
2465 ast.Node.GroupedExpression {
2466 .base = undefined,
2467 .lparen = token.index,
2468 .expr = undefined,
2469 .rparen = undefined,
2470 }
2471 );
2443 const node = try arena.construct(ast.Node.GroupedExpression {
2444 .base = ast.Node {.id = ast.Node.Id.GroupedExpression },
2445 .lparen = token.index,
2446 .expr = undefined,
2447 .rparen = undefined,
2448 });
2449 opt_ctx.store(&node.base);
2450
24722451 stack.append(State {
24732452 .ExpectTokenSave = ExpectTokenSave {
24742453 .id = Token.Id.RParen,
......@@ -2479,14 +2458,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24792458 continue;
24802459 },
24812460 Token.Id.Builtin => {
2482 const node = try createToCtxNode(arena, opt_ctx, ast.Node.BuiltinCall,
2483 ast.Node.BuiltinCall {
2484 .base = undefined,
2485 .builtin_token = token.index,
2486 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2487 .rparen_token = undefined,
2488 }
2489 );
2461 const node = try arena.construct(ast.Node.BuiltinCall {
2462 .base = ast.Node {.id = ast.Node.Id.BuiltinCall },
2463 .builtin_token = token.index,
2464 .params = ast.Node.BuiltinCall.ParamList.init(arena),
2465 .rparen_token = undefined,
2466 });
2467 opt_ctx.store(&node.base);
2468
24902469 stack.append(State {
24912470 .ExprListItemOrEnd = ExprListCtx {
24922471 .list = &node.params,
......@@ -2498,14 +2477,14 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
24982477 continue;
24992478 },
25002479 Token.Id.LBracket => {
2501 const node = try createToCtxNode(arena, opt_ctx, ast.Node.PrefixOp,
2502 ast.Node.PrefixOp {
2503 .base = undefined,
2504 .op_token = token.index,
2505 .op = undefined,
2506 .rhs = undefined,
2507 }
2508 );
2480 const node = try arena.construct(ast.Node.PrefixOp {
2481 .base = ast.Node {.id = ast.Node.Id.PrefixOp },
2482 .op_token = token.index,
2483 .op = undefined,
2484 .rhs = undefined,
2485 });
2486 opt_ctx.store(&node.base);
2487
25092488 stack.append(State { .SliceOrArrayType = node }) catch unreachable;
25102489 continue;
25112490 },
......@@ -2611,18 +2590,18 @@ pub fn parse(allocator: &mem.Allocator, source: []const u8) !ast.Tree {
26112590 continue;
26122591 },
26132592 Token.Id.Keyword_asm => {
2614 const node = try createToCtxNode(arena, opt_ctx, ast.Node.Asm,
2615 ast.Node.Asm {
2616 .base = undefined,
2617 .asm_token = token.index,
2618 .volatile_token = null,
2619 .template = undefined,
2620 .outputs = ast.Node.Asm.OutputList.init(arena),
2621 .inputs = ast.Node.Asm.InputList.init(arena),
2622 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2623 .rparen = undefined,
2624 }
2625 );
2593 const node = try arena.construct(ast.Node.Asm {
2594 .base = ast.Node {.id = ast.Node.Id.Asm },
2595 .asm_token = token.index,
2596 .volatile_token = null,
2597 .template = undefined,
2598 .outputs = ast.Node.Asm.OutputList.init(arena),
2599 .inputs = ast.Node.Asm.InputList.init(arena),
2600 .clobbers = ast.Node.Asm.ClobberList.init(arena),
2601 .rparen = undefined,
2602 });
2603 opt_ctx.store(&node.base);
2604
26262605 stack.append(State {
26272606 .ExpectTokenSave = ExpectTokenSave {
26282607 .id = Token.Id.RParen,
......@@ -2978,6 +2957,7 @@ const State = union(enum) {
29782957 VarDecl: VarDeclCtx,
29792958 VarDeclAlign: &ast.Node.VarDecl,
29802959 VarDeclEq: &ast.Node.VarDecl,
2960 VarDeclSemiColon: &ast.Node.VarDecl,
29812961
29822962 FnDef: &ast.Node.FnProto,
29832963 FnProto: &ast.Node.FnProto,
......@@ -3082,25 +3062,29 @@ const State = union(enum) {
30823062 OptionalTokenSave: OptionalTokenSave,
30833063};
30843064
3065fn pushDocComment(arena: &mem.Allocator, line_comment: TokenIndex, result: &?&ast.Node.DocComment) !void {
3066 const node = blk: {
3067 if (*result) |comment_node| {
3068 break :blk comment_node;
3069 } else {
3070 const comment_node = try arena.construct(ast.Node.DocComment {
3071 .base = ast.Node {
3072 .id = ast.Node.Id.DocComment,
3073 },
3074 .lines = ast.Node.DocComment.LineList.init(arena),
3075 });
3076 *result = comment_node;
3077 break :blk comment_node;
3078 }
3079 };
3080 try node.lines.push(line_comment);
3081}
3082
30853083fn eatDocComments(arena: &mem.Allocator, tok_it: &ast.Tree.TokenList.Iterator, tree: &ast.Tree) !?&ast.Node.DocComment {
30863084 var result: ?&ast.Node.DocComment = null;
30873085 while (true) {
30883086 if (eatToken(tok_it, tree, Token.Id.DocComment)) |line_comment| {
3089 const node = blk: {
3090 if (result) |comment_node| {
3091 break :blk comment_node;
3092 } else {
3093 const comment_node = try arena.construct(ast.Node.DocComment {
3094 .base = ast.Node {
3095 .id = ast.Node.Id.DocComment,
3096 },
3097 .lines = ast.Node.DocComment.LineList.init(arena),
3098 });
3099 result = comment_node;
3100 break :blk comment_node;
3101 }
3102 };
3103 try node.lines.push(line_comment);
3087 try pushDocComment(arena, line_comment, &result);
31043088 continue;
31053089 }
31063090 break;
......@@ -3155,31 +3139,29 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con
31553139 token_ptr: &const Token, token_index: TokenIndex) !bool {
31563140 switch (token_ptr.id) {
31573141 Token.Id.Keyword_suspend => {
3158 const node = try createToCtxNode(arena, ctx, ast.Node.Suspend,
3159 ast.Node.Suspend {
3160 .base = undefined,
3161 .label = null,
3162 .suspend_token = token_index,
3163 .payload = null,
3164 .body = null,
3165 }
3166 );
3142 const node = try arena.construct(ast.Node.Suspend {
3143 .base = ast.Node {.id = ast.Node.Id.Suspend },
3144 .label = null,
3145 .suspend_token = token_index,
3146 .payload = null,
3147 .body = null,
3148 });
3149 ctx.store(&node.base);
31673150
31683151 stack.append(State { .SuspendBody = node }) catch unreachable;
31693152 try stack.append(State { .Payload = OptionalCtx { .Optional = &node.payload } });
31703153 return true;
31713154 },
31723155 Token.Id.Keyword_if => {
3173 const node = try createToCtxNode(arena, ctx, ast.Node.If,
3174 ast.Node.If {
3175 .base = undefined,
3176 .if_token = token_index,
3177 .condition = undefined,
3178 .payload = null,
3179 .body = undefined,
3180 .@"else" = null,
3181 }
3182 );
3156 const node = try arena.construct(ast.Node.If {
3157 .base = ast.Node {.id = ast.Node.Id.If },
3158 .if_token = token_index,
3159 .condition = undefined,
3160 .payload = null,
3161 .body = undefined,
3162 .@"else" = null,
3163 });
3164 ctx.store(&node.base);
31833165
31843166 stack.append(State { .Else = &node.@"else" }) catch unreachable;
31853167 try stack.append(State { .Expression = OptionalCtx { .Required = &node.body } });
......@@ -3236,14 +3218,14 @@ fn parseBlockExpr(stack: &std.ArrayList(State), arena: &mem.Allocator, ctx: &con
32363218 return true;
32373219 },
32383220 Token.Id.Keyword_comptime => {
3239 const node = try createToCtxNode(arena, ctx, ast.Node.Comptime,
3240 ast.Node.Comptime {
3241 .base = undefined,
3242 .comptime_token = token_index,
3243 .expr = undefined,
3244 .doc_comments = null,
3245 }
3246 );
3221 const node = try arena.construct(ast.Node.Comptime {
3222 .base = ast.Node {.id = ast.Node.Id.Comptime },
3223 .comptime_token = token_index,
3224 .expr = undefined,
3225 .doc_comments = null,
3226 });
3227 ctx.store(&node.base);
3228
32473229 try stack.append(State { .Expression = OptionalCtx { .Required = &node.expr } });
32483230 return true;
32493231 },
......@@ -3390,33 +3372,11 @@ fn tokenIdToPrefixOp(id: @TagType(Token.Id)) ?ast.Node.PrefixOp.Op {
33903372 };
33913373}
33923374
3393fn createNode(arena: &mem.Allocator, comptime T: type, init_to: &const T) !&T {
3394 const node = try arena.create(T);
3395 *node = *init_to;
3396 node.base = blk: {
3397 const id = ast.Node.typeToId(T);
3398 break :blk ast.Node {
3399 .id = id,
3400 };
3401 };
3402
3403 return node;
3404}
3405
3406fn createToCtxNode(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, init_to: &const T) !&T {
3407 const node = try createNode(arena, T, init_to);
3408 opt_ctx.store(&node.base);
3409
3410 return node;
3411}
3412
34133375fn createLiteral(arena: &mem.Allocator, comptime T: type, token_index: TokenIndex) !&T {
3414 return createNode(arena, T,
3415 T {
3416 .base = undefined,
3417 .token = token_index,
3418 }
3419 );
3376 return arena.construct(T {
3377 .base = ast.Node {.id = ast.Node.typeToId(T)},
3378 .token = token_index,
3379 });
34203380}
34213381
34223382fn createToCtxLiteral(arena: &mem.Allocator, opt_ctx: &const OptionalCtx, comptime T: type, token_index: TokenIndex) !&T {
std/zig/parser_test.zig+14
......@@ -1,3 +1,17 @@
1test "zig fmt: same-line doc comment on variable declaration" {
2 try testTransform(
3 \\pub const MAP_ANONYMOUS = 0x1000; /// allocated from memory, swap space
4 \\pub const MAP_FILE = 0x0000; /// map from file (default)
5 \\
6 ,
7 \\/// allocated from memory, swap space
8 \\pub const MAP_ANONYMOUS = 0x1000;
9 \\/// map from file (default)
10 \\pub const MAP_FILE = 0x0000;
11 \\
12 );
13}
14
115test "zig fmt: same-line comment after a statement" {
216 try testCanonical(
317 \\test "" {
test/cases/type_info.zig+177-142
......@@ -4,167 +4,199 @@ const TypeInfo = @import("builtin").TypeInfo;
44const TypeId = @import("builtin").TypeId;
55
66test "type info: tag type, void info" {
7 comptime {
8 assert(@TagType(TypeInfo) == TypeId);
9 const void_info = @typeInfo(void);
10 assert(TypeId(void_info) == TypeId.Void);
11 assert(void_info.Void == {});
12 }
7 testBasic();
8 comptime testBasic();
9}
10
11fn testBasic() void {
12 assert(@TagType(TypeInfo) == TypeId);
13 const void_info = @typeInfo(void);
14 assert(TypeId(void_info) == TypeId.Void);
15 assert(void_info.Void == {});
1316}
1417
1518test "type info: integer, floating point type info" {
16 comptime {
17 const u8_info = @typeInfo(u8);
18 assert(TypeId(u8_info) == TypeId.Int);
19 assert(!u8_info.Int.is_signed);
20 assert(u8_info.Int.bits == 8);
19 testIntFloat();
20 comptime testIntFloat();
21}
2122
22 const f64_info = @typeInfo(f64);
23 assert(TypeId(f64_info) == TypeId.Float);
24 assert(f64_info.Float.bits == 64);
25 }
23fn testIntFloat() void {
24 const u8_info = @typeInfo(u8);
25 assert(TypeId(u8_info) == TypeId.Int);
26 assert(!u8_info.Int.is_signed);
27 assert(u8_info.Int.bits == 8);
28
29 const f64_info = @typeInfo(f64);
30 assert(TypeId(f64_info) == TypeId.Float);
31 assert(f64_info.Float.bits == 64);
2632}
2733
2834test "type info: pointer type info" {
29 comptime {
30 const u32_ptr_info = @typeInfo(&u32);
31 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
32 assert(u32_ptr_info.Pointer.is_const == false);
33 assert(u32_ptr_info.Pointer.is_volatile == false);
34 assert(u32_ptr_info.Pointer.alignment == 4);
35 assert(u32_ptr_info.Pointer.child == u32);
36 }
35 testPointer();
36 comptime testPointer();
37}
38
39fn testPointer() void {
40 const u32_ptr_info = @typeInfo(&u32);
41 assert(TypeId(u32_ptr_info) == TypeId.Pointer);
42 assert(u32_ptr_info.Pointer.is_const == false);
43 assert(u32_ptr_info.Pointer.is_volatile == false);
44 assert(u32_ptr_info.Pointer.alignment == 4);
45 assert(u32_ptr_info.Pointer.child == u32);
3746}
3847
3948test "type info: slice type info" {
40 comptime {
41 const u32_slice_info = @typeInfo([]u32);
42 assert(TypeId(u32_slice_info) == TypeId.Slice);
43 assert(u32_slice_info.Slice.is_const == false);
44 assert(u32_slice_info.Slice.is_volatile == false);
45 assert(u32_slice_info.Slice.alignment == 4);
46 assert(u32_slice_info.Slice.child == u32);
47 }
49 testSlice();
50 comptime testSlice();
51}
52
53fn testSlice() void {
54 const u32_slice_info = @typeInfo([]u32);
55 assert(TypeId(u32_slice_info) == TypeId.Slice);
56 assert(u32_slice_info.Slice.is_const == false);
57 assert(u32_slice_info.Slice.is_volatile == false);
58 assert(u32_slice_info.Slice.alignment == 4);
59 assert(u32_slice_info.Slice.child == u32);
4860}
4961
5062test "type info: array type info" {
51 comptime {
52 const arr_info = @typeInfo([42]bool);
53 assert(TypeId(arr_info) == TypeId.Array);
54 assert(arr_info.Array.len == 42);
55 assert(arr_info.Array.child == bool);
56 }
63 testArray();
64 comptime testArray();
65}
66
67fn testArray() void {
68 const arr_info = @typeInfo([42]bool);
69 assert(TypeId(arr_info) == TypeId.Array);
70 assert(arr_info.Array.len == 42);
71 assert(arr_info.Array.child == bool);
5772}
5873
5974test "type info: nullable type info" {
60 comptime {
61 const null_info = @typeInfo(?void);
62 assert(TypeId(null_info) == TypeId.Nullable);
63 assert(null_info.Nullable.child == void);
64 }
75 testNullable();
76 comptime testNullable();
77}
78
79fn testNullable() void {
80 const null_info = @typeInfo(?void);
81 assert(TypeId(null_info) == TypeId.Nullable);
82 assert(null_info.Nullable.child == void);
6583}
6684
6785test "type info: promise info" {
68 comptime {
69 const null_promise_info = @typeInfo(promise);
70 assert(TypeId(null_promise_info) == TypeId.Promise);
71 assert(null_promise_info.Promise.child == @typeOf(undefined));
86 testPromise();
87 comptime testPromise();
88}
7289
73 const promise_info = @typeInfo(promise->usize);
74 assert(TypeId(promise_info) == TypeId.Promise);
75 assert(promise_info.Promise.child == usize);
76 }
90fn testPromise() void {
91 const null_promise_info = @typeInfo(promise);
92 assert(TypeId(null_promise_info) == TypeId.Promise);
93 assert(null_promise_info.Promise.child == @typeOf(undefined));
7794
95 const promise_info = @typeInfo(promise->usize);
96 assert(TypeId(promise_info) == TypeId.Promise);
97 assert(promise_info.Promise.child == usize);
7898}
7999
80100test "type info: error set, error union info" {
81 comptime {
82 const TestErrorSet = error {
83 First,
84 Second,
85 Third,
86 };
87
88 const error_set_info = @typeInfo(TestErrorSet);
89 assert(TypeId(error_set_info) == TypeId.ErrorSet);
90 assert(error_set_info.ErrorSet.errors.len == 3);
91 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
92 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
93
94 const error_union_info = @typeInfo(TestErrorSet!usize);
95 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
96 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
97 assert(error_union_info.ErrorUnion.payload == usize);
98 }
101 testErrorSet();
102 comptime testErrorSet();
103}
104
105fn testErrorSet() void {
106 const TestErrorSet = error {
107 First,
108 Second,
109 Third,
110 };
111
112 const error_set_info = @typeInfo(TestErrorSet);
113 assert(TypeId(error_set_info) == TypeId.ErrorSet);
114 assert(error_set_info.ErrorSet.errors.len == 3);
115 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
116 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));
117
118 const error_union_info = @typeInfo(TestErrorSet!usize);
119 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
120 assert(error_union_info.ErrorUnion.error_set == TestErrorSet);
121 assert(error_union_info.ErrorUnion.payload == usize);
99122}
100123
101124test "type info: enum info" {
102 comptime {
103 const Os = @import("builtin").Os;
125 testEnum();
126 comptime testEnum();
127}
104128
105 const os_info = @typeInfo(Os);
106 assert(TypeId(os_info) == TypeId.Enum);
107 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
108 assert(os_info.Enum.fields.len == 32);
109 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
110 assert(os_info.Enum.fields[10].value == 10);
111 assert(os_info.Enum.tag_type == u5);
112 assert(os_info.Enum.defs.len == 0);
113 }
129fn testEnum() void {
130 const Os = @import("builtin").Os;
131
132 const os_info = @typeInfo(Os);
133 assert(TypeId(os_info) == TypeId.Enum);
134 assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto);
135 assert(os_info.Enum.fields.len == 32);
136 assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas"));
137 assert(os_info.Enum.fields[10].value == 10);
138 assert(os_info.Enum.tag_type == u5);
139 assert(os_info.Enum.defs.len == 0);
114140}
115141
116142test "type info: union info" {
117 comptime {
118 const typeinfo_info = @typeInfo(TypeInfo);
119 assert(TypeId(typeinfo_info) == TypeId.Union);
120 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
121 assert(typeinfo_info.Union.tag_type == TypeId);
122 assert(typeinfo_info.Union.fields.len == 26);
123 assert(typeinfo_info.Union.fields[4].enum_field != null);
124 assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
125 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
126 assert(typeinfo_info.Union.defs.len == 21);
127
128 const TestNoTagUnion = union {
129 Foo: void,
130 Bar: u32,
131 };
132
133 const notag_union_info = @typeInfo(TestNoTagUnion);
134 assert(TypeId(notag_union_info) == TypeId.Union);
135 assert(notag_union_info.Union.tag_type == @typeOf(undefined));
136 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
137 assert(notag_union_info.Union.fields.len == 2);
138 assert(notag_union_info.Union.fields[0].enum_field == null);
139 assert(notag_union_info.Union.fields[1].field_type == u32);
140
141 const TestExternUnion = extern union {
142 foo: &c_void,
143 };
144
145 const extern_union_info = @typeInfo(TestExternUnion);
146 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
147 assert(extern_union_info.Union.tag_type == @typeOf(undefined));
148 assert(extern_union_info.Union.fields[0].enum_field == null);
149 assert(extern_union_info.Union.fields[0].field_type == &c_void);
150 }
143 testUnion();
144 comptime testUnion();
145}
146
147fn testUnion() void {
148 const typeinfo_info = @typeInfo(TypeInfo);
149 assert(TypeId(typeinfo_info) == TypeId.Union);
150 assert(typeinfo_info.Union.layout == TypeInfo.ContainerLayout.Auto);
151 assert(typeinfo_info.Union.tag_type == TypeId);
152 assert(typeinfo_info.Union.fields.len == 26);
153 assert(typeinfo_info.Union.fields[4].enum_field != null);
154 assert((??typeinfo_info.Union.fields[4].enum_field).value == 4);
155 assert(typeinfo_info.Union.fields[4].field_type == @typeOf(@typeInfo(u8).Int));
156 assert(typeinfo_info.Union.defs.len == 21);
157
158 const TestNoTagUnion = union {
159 Foo: void,
160 Bar: u32,
161 };
162
163 const notag_union_info = @typeInfo(TestNoTagUnion);
164 assert(TypeId(notag_union_info) == TypeId.Union);
165 assert(notag_union_info.Union.tag_type == @typeOf(undefined));
166 assert(notag_union_info.Union.layout == TypeInfo.ContainerLayout.Auto);
167 assert(notag_union_info.Union.fields.len == 2);
168 assert(notag_union_info.Union.fields[0].enum_field == null);
169 assert(notag_union_info.Union.fields[1].field_type == u32);
170
171 const TestExternUnion = extern union {
172 foo: &c_void,
173 };
174
175 const extern_union_info = @typeInfo(TestExternUnion);
176 assert(extern_union_info.Union.layout == TypeInfo.ContainerLayout.Extern);
177 assert(extern_union_info.Union.tag_type == @typeOf(undefined));
178 assert(extern_union_info.Union.fields[0].enum_field == null);
179 assert(extern_union_info.Union.fields[0].field_type == &c_void);
151180}
152181
153182test "type info: struct info" {
154 comptime {
155 const struct_info = @typeInfo(TestStruct);
156 assert(TypeId(struct_info) == TypeId.Struct);
157 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
158 assert(struct_info.Struct.fields.len == 3);
159 assert(struct_info.Struct.fields[1].offset == null);
160 assert(struct_info.Struct.fields[2].field_type == &TestStruct);
161 assert(struct_info.Struct.defs.len == 2);
162 assert(struct_info.Struct.defs[0].is_pub);
163 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
164 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
165 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
166 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
167 }
183 testStruct();
184 comptime testStruct();
185}
186
187fn testStruct() void {
188 const struct_info = @typeInfo(TestStruct);
189 assert(TypeId(struct_info) == TypeId.Struct);
190 assert(struct_info.Struct.layout == TypeInfo.ContainerLayout.Packed);
191 assert(struct_info.Struct.fields.len == 3);
192 assert(struct_info.Struct.fields[1].offset == null);
193 assert(struct_info.Struct.fields[2].field_type == &TestStruct);
194 assert(struct_info.Struct.defs.len == 2);
195 assert(struct_info.Struct.defs[0].is_pub);
196 assert(!struct_info.Struct.defs[0].data.Fn.is_extern);
197 assert(struct_info.Struct.defs[0].data.Fn.lib_name == null);
198 assert(struct_info.Struct.defs[0].data.Fn.return_type == void);
199 assert(struct_info.Struct.defs[0].data.Fn.fn_type == fn(&const TestStruct)void);
168200}
169201
170202const TestStruct = packed struct {
......@@ -178,21 +210,24 @@ const TestStruct = packed struct {
178210};
179211
180212test "type info: function type info" {
181 comptime {
182 const fn_info = @typeInfo(@typeOf(foo));
183 assert(TypeId(fn_info) == TypeId.Fn);
184 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
185 assert(fn_info.Fn.is_generic);
186 assert(fn_info.Fn.args.len == 2);
187 assert(fn_info.Fn.is_var_args);
188 assert(fn_info.Fn.return_type == @typeOf(undefined));
189 assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
190
191 const test_instance: TestStruct = undefined;
192 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
193 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
194 assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
195 }
213 testFunction();
214 comptime testFunction();
215}
216
217fn testFunction() void {
218 const fn_info = @typeInfo(@typeOf(foo));
219 assert(TypeId(fn_info) == TypeId.Fn);
220 assert(fn_info.Fn.calling_convention == TypeInfo.CallingConvention.Unspecified);
221 assert(fn_info.Fn.is_generic);
222 assert(fn_info.Fn.args.len == 2);
223 assert(fn_info.Fn.is_var_args);
224 assert(fn_info.Fn.return_type == @typeOf(undefined));
225 assert(fn_info.Fn.async_allocator_type == @typeOf(undefined));
226
227 const test_instance: TestStruct = undefined;
228 const bound_fn_info = @typeInfo(@typeOf(test_instance.foo));
229 assert(TypeId(bound_fn_info) == TypeId.BoundFn);
230 assert(bound_fn_info.BoundFn.args[0].arg_type == &const TestStruct);
196231}
197232
198233fn foo(comptime a: usize, b: bool, args: ...) usize {