| author | |
| committer | |
| log | b4d81857f36a155daa884ba80bfd56c43a182663 |
| tree | 3cf2a9e926f40fa6326f4a7c9827f286b41526f2 |
| parent | 8849792789331faec0caaca18822227ecdb9bc62 |
6 files changed, 71 insertions(+), 15 deletions(-)
lib/std/zig/Ast.zig+28-3| ... | ... | @@ -643,11 +643,23 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex { |
| 643 | 643 | n = datas[n].lhs; |
| 644 | 644 | } |
| 645 | 645 | }, |
| 646 | .switch_case_inline_one => { | |
| 647 | if (datas[n].lhs == 0) { | |
| 648 | return main_tokens[n] - 2 - end_offset; // else token | |
| 649 | } else { | |
| 650 | return firstToken(tree, datas[n].lhs) - 1; | |
| 651 | } | |
| 652 | }, | |
| 646 | 653 | .switch_case => { |
| 647 | 654 | const extra = tree.extraData(datas[n].lhs, Node.SubRange); |
| 648 | 655 | assert(extra.end - extra.start > 0); |
| 649 | 656 | n = tree.extra_data[extra.start]; |
| 650 | 657 | }, |
| 658 | .switch_case_inline => { | |
| 659 | const extra = tree.extraData(datas[n].lhs, Node.SubRange); | |
| 660 | assert(extra.end - extra.start > 0); | |
| 661 | return firstToken(tree, tree.extra_data[extra.start]) - 1; | |
| 662 | }, | |
| 651 | 663 | |
| 652 | 664 | .asm_output, .asm_input => { |
| 653 | 665 | assert(token_tags[main_tokens[n] - 1] == .l_bracket); |
| ... | ... | @@ -763,7 +775,9 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex { |
| 763 | 775 | .ptr_type_bit_range, |
| 764 | 776 | .array_type, |
| 765 | 777 | .switch_case_one, |
| 778 | .switch_case_inline_one, | |
| 766 | 779 | .switch_case, |
| 780 | .switch_case_inline, | |
| 767 | 781 | .switch_range, |
| 768 | 782 | => n = datas[n].rhs, |
| 769 | 783 | |
| ... | ... | @@ -1755,7 +1769,7 @@ pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1755 | 1769 | .values = if (data.lhs == 0) values[0..0] else values[0..1], |
| 1756 | 1770 | .arrow_token = tree.nodes.items(.main_token)[node], |
| 1757 | 1771 | .target_expr = data.rhs, |
| 1758 | }); | |
| 1772 | }, node); | |
| 1759 | 1773 | } |
| 1760 | 1774 | |
| 1761 | 1775 | pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase { |
| ... | ... | @@ -1765,7 +1779,7 @@ pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase { |
| 1765 | 1779 | .values = tree.extra_data[extra.start..extra.end], |
| 1766 | 1780 | .arrow_token = tree.nodes.items(.main_token)[node], |
| 1767 | 1781 | .target_expr = data.rhs, |
| 1768 | }); | |
| 1782 | }, node); | |
| 1769 | 1783 | } |
| 1770 | 1784 | |
| 1771 | 1785 | pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm { |
| ... | ... | @@ -2038,15 +2052,21 @@ fn fullContainerDecl(tree: Ast, info: full.ContainerDecl.Components) full.Contai |
| 2038 | 2052 | return result; |
| 2039 | 2053 | } |
| 2040 | 2054 | |
| 2041 | fn fullSwitchCase(tree: Ast, info: full.SwitchCase.Components) full.SwitchCase { | |
| 2055 | fn fullSwitchCase(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase { | |
| 2042 | 2056 | const token_tags = tree.tokens.items(.tag); |
| 2057 | const node_tags = tree.nodes.items(.tag); | |
| 2043 | 2058 | var result: full.SwitchCase = .{ |
| 2044 | 2059 | .ast = info, |
| 2045 | 2060 | .payload_token = null, |
| 2061 | .inline_token = null, | |
| 2046 | 2062 | }; |
| 2047 | 2063 | if (token_tags[info.arrow_token + 1] == .pipe) { |
| 2048 | 2064 | result.payload_token = info.arrow_token + 2; |
| 2049 | 2065 | } |
| 2066 | switch (node_tags[node]) { | |
| 2067 | .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node), | |
| 2068 | else => {}, | |
| 2069 | } | |
| 2050 | 2070 | return result; |
| 2051 | 2071 | } |
| 2052 | 2072 | |
| ... | ... | @@ -2454,6 +2474,7 @@ pub const full = struct { |
| 2454 | 2474 | }; |
| 2455 | 2475 | |
| 2456 | 2476 | pub const SwitchCase = struct { |
| 2477 | inline_token: ?TokenIndex, | |
| 2457 | 2478 | /// Points to the first token after the `|`. Will either be an identifier or |
| 2458 | 2479 | /// a `*` (with an identifier immediately after it). |
| 2459 | 2480 | payload_token: ?TokenIndex, |
| ... | ... | @@ -2847,9 +2868,13 @@ pub const Node = struct { |
| 2847 | 2868 | /// `lhs => rhs`. If lhs is omitted it means `else`. |
| 2848 | 2869 | /// main_token is the `=>` |
| 2849 | 2870 | switch_case_one, |
| 2871 | /// Same ast `switch_case_one` but the case is inline | |
| 2872 | switch_case_inline_one, | |
| 2850 | 2873 | /// `a, b, c => rhs`. `SubRange[lhs]`. |
| 2851 | 2874 | /// main_token is the `=>` |
| 2852 | 2875 | switch_case, |
| 2876 | /// Same ast `switch_case` but the case is inline | |
| 2877 | switch_case_inline, | |
| 2853 | 2878 | /// `lhs...rhs`. |
| 2854 | 2879 | switch_range, |
| 2855 | 2880 | /// `while (lhs) rhs`. |
lib/std/zig/parse.zig+10-5| ... | ... | @@ -3100,7 +3100,7 @@ const Parser = struct { |
| 3100 | 3100 | return identifier; |
| 3101 | 3101 | } |
| 3102 | 3102 | |
| 3103 | /// SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr | |
| 3103 | /// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrPayload? AssignExpr | |
| 3104 | 3104 | /// SwitchCase |
| 3105 | 3105 | /// <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 3106 | 3106 | /// / KEYWORD_else |
| ... | ... | @@ -3108,6 +3108,8 @@ const Parser = struct { |
| 3108 | 3108 | const scratch_top = p.scratch.items.len; |
| 3109 | 3109 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3110 | 3110 | |
| 3111 | const is_inline = p.eatToken(.keyword_inline) != null; | |
| 3112 | ||
| 3111 | 3113 | if (p.eatToken(.keyword_else) == null) { |
| 3112 | 3114 | while (true) { |
| 3113 | 3115 | const item = try p.parseSwitchItem(); |
| ... | ... | @@ -3115,7 +3117,10 @@ const Parser = struct { |
| 3115 | 3117 | try p.scratch.append(p.gpa, item); |
| 3116 | 3118 | if (p.eatToken(.comma) == null) break; |
| 3117 | 3119 | } |
| 3118 | if (scratch_top == p.scratch.items.len) return null_node; | |
| 3120 | if (scratch_top == p.scratch.items.len) { | |
| 3121 | if (is_inline) p.tok_i -= 1; | |
| 3122 | return null_node; | |
| 3123 | } | |
| 3119 | 3124 | } |
| 3120 | 3125 | const arrow_token = try p.expectToken(.equal_angle_bracket_right); |
| 3121 | 3126 | _ = try p.parsePtrPayload(); |
| ... | ... | @@ -3123,7 +3128,7 @@ const Parser = struct { |
| 3123 | 3128 | const items = p.scratch.items[scratch_top..]; |
| 3124 | 3129 | switch (items.len) { |
| 3125 | 3130 | 0 => return p.addNode(.{ |
| 3126 | .tag = .switch_case_one, | |
| 3131 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, | |
| 3127 | 3132 | .main_token = arrow_token, |
| 3128 | 3133 | .data = .{ |
| 3129 | 3134 | .lhs = 0, |
| ... | ... | @@ -3131,7 +3136,7 @@ const Parser = struct { |
| 3131 | 3136 | }, |
| 3132 | 3137 | }), |
| 3133 | 3138 | 1 => return p.addNode(.{ |
| 3134 | .tag = .switch_case_one, | |
| 3139 | .tag = if (is_inline) .switch_case_inline_one else .switch_case_one, | |
| 3135 | 3140 | .main_token = arrow_token, |
| 3136 | 3141 | .data = .{ |
| 3137 | 3142 | .lhs = items[0], |
| ... | ... | @@ -3139,7 +3144,7 @@ const Parser = struct { |
| 3139 | 3144 | }, |
| 3140 | 3145 | }), |
| 3141 | 3146 | else => return p.addNode(.{ |
| 3142 | .tag = .switch_case, | |
| 3147 | .tag = if (is_inline) .switch_case_inline else .switch_case, | |
| 3143 | 3148 | .main_token = arrow_token, |
| 3144 | 3149 | .data = .{ |
| 3145 | 3150 | .lhs = try p.addExtra(try p.listToSpan(items)), |
lib/std/zig/render.zig+7-2| ... | ... | @@ -685,8 +685,8 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index, |
| 685 | 685 | return renderToken(ais, tree, tree.lastToken(node), space); // rbrace |
| 686 | 686 | }, |
| 687 | 687 | |
| 688 | .switch_case_one => return renderSwitchCase(gpa, ais, tree, tree.switchCaseOne(node), space), | |
| 689 | .switch_case => return renderSwitchCase(gpa, ais, tree, tree.switchCase(node), space), | |
| 688 | .switch_case_one, .switch_case_inline_one => return renderSwitchCase(gpa, ais, tree, tree.switchCaseOne(node), space), | |
| 689 | .switch_case, .switch_case_inline => return renderSwitchCase(gpa, ais, tree, tree.switchCase(node), space), | |
| 690 | 690 | |
| 691 | 691 | .while_simple => return renderWhile(gpa, ais, tree, tree.whileSimple(node), space), |
| 692 | 692 | .while_cont => return renderWhile(gpa, ais, tree, tree.whileCont(node), space), |
| ... | ... | @@ -1509,6 +1509,11 @@ fn renderSwitchCase( |
| 1509 | 1509 | break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token); |
| 1510 | 1510 | }; |
| 1511 | 1511 | |
| 1512 | // render inline keyword | |
| 1513 | if (switch_case.inline_token) |some| { | |
| 1514 | try renderToken(ais, tree, some, .space); | |
| 1515 | } | |
| 1516 | ||
| 1512 | 1517 | // Render everything before the arrow |
| 1513 | 1518 | if (switch_case.ast.values.len == 0) { |
| 1514 | 1519 | try renderToken(ais, tree, switch_case.ast.arrow_token - 1, .space); // else keyword |
src/AstGen.zig+16-2| ... | ... | @@ -386,7 +386,9 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins |
| 386 | 386 | .simple_var_decl => unreachable, |
| 387 | 387 | .aligned_var_decl => unreachable, |
| 388 | 388 | .switch_case => unreachable, |
| 389 | .switch_case_inline => unreachable, | |
| 389 | 390 | .switch_case_one => unreachable, |
| 391 | .switch_case_inline_one => unreachable, | |
| 390 | 392 | .container_field_init => unreachable, |
| 391 | 393 | .container_field_align => unreachable, |
| 392 | 394 | .container_field => unreachable, |
| ... | ... | @@ -600,7 +602,9 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr |
| 600 | 602 | .@"errdefer" => unreachable, // Handled in `blockExpr`. |
| 601 | 603 | |
| 602 | 604 | .switch_case => unreachable, // Handled in `switchExpr`. |
| 605 | .switch_case_inline => unreachable, // Handled in `switchExpr`. | |
| 603 | 606 | .switch_case_one => unreachable, // Handled in `switchExpr`. |
| 607 | .switch_case_inline_one => unreachable, // Handled in `switchExpr`. | |
| 604 | 608 | .switch_range => unreachable, // Handled in `switchExpr`. |
| 605 | 609 | |
| 606 | 610 | .asm_output => unreachable, // Handled in `asmExpr`. |
| ... | ... | @@ -6216,14 +6220,15 @@ fn switchExpr( |
| 6216 | 6220 | var any_payload_is_ref = false; |
| 6217 | 6221 | var scalar_cases_len: u32 = 0; |
| 6218 | 6222 | var multi_cases_len: u32 = 0; |
| 6223 | var inline_cases_len: u32 = 0; | |
| 6219 | 6224 | var special_prong: Zir.SpecialProng = .none; |
| 6220 | 6225 | var special_node: Ast.Node.Index = 0; |
| 6221 | 6226 | var else_src: ?Ast.TokenIndex = null; |
| 6222 | 6227 | var underscore_src: ?Ast.TokenIndex = null; |
| 6223 | 6228 | for (case_nodes) |case_node| { |
| 6224 | 6229 | const case = switch (node_tags[case_node]) { |
| 6225 | .switch_case_one => tree.switchCaseOne(case_node), | |
| 6226 | .switch_case => tree.switchCase(case_node), | |
| 6230 | .switch_case_one, .switch_case_inline_one => tree.switchCaseOne(case_node), | |
| 6231 | .switch_case, .switch_case_inline => tree.switchCase(case_node), | |
| 6227 | 6232 | else => unreachable, |
| 6228 | 6233 | }; |
| 6229 | 6234 | if (case.payload_token) |payload_token| { |
| ... | ... | @@ -6318,6 +6323,9 @@ fn switchExpr( |
| 6318 | 6323 | } else { |
| 6319 | 6324 | multi_cases_len += 1; |
| 6320 | 6325 | } |
| 6326 | if (case.inline_token != null) { | |
| 6327 | inline_cases_len += 1; | |
| 6328 | } | |
| 6321 | 6329 | } |
| 6322 | 6330 | |
| 6323 | 6331 | const operand_rl: ResultLoc = if (any_payload_is_ref) .ref else .none; |
| ... | ... | @@ -8436,7 +8444,9 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_ |
| 8436 | 8444 | .@"usingnamespace", |
| 8437 | 8445 | .test_decl, |
| 8438 | 8446 | .switch_case, |
| 8447 | .switch_case_inline, | |
| 8439 | 8448 | .switch_case_one, |
| 8449 | .switch_case_inline_one, | |
| 8440 | 8450 | .container_field_init, |
| 8441 | 8451 | .container_field_align, |
| 8442 | 8452 | .container_field, |
| ... | ... | @@ -8668,7 +8678,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev |
| 8668 | 8678 | .@"usingnamespace", |
| 8669 | 8679 | .test_decl, |
| 8670 | 8680 | .switch_case, |
| 8681 | .switch_case_inline, | |
| 8671 | 8682 | .switch_case_one, |
| 8683 | .switch_case_inline_one, | |
| 8672 | 8684 | .container_field_init, |
| 8673 | 8685 | .container_field_align, |
| 8674 | 8686 | .container_field, |
| ... | ... | @@ -8879,7 +8891,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In |
| 8879 | 8891 | .@"usingnamespace", |
| 8880 | 8892 | .test_decl, |
| 8881 | 8893 | .switch_case, |
| 8894 | .switch_case_inline, | |
| 8882 | 8895 | .switch_case_one, |
| 8896 | .switch_case_inline_one, | |
| 8883 | 8897 | .container_field_init, |
| 8884 | 8898 | .container_field_align, |
| 8885 | 8899 | .container_field, |
src/stage1/all_types.hpp+1| ... | ... | @@ -1039,6 +1039,7 @@ struct AstNodeSwitchProng { |
| 1039 | 1039 | AstNode *expr; |
| 1040 | 1040 | bool var_is_ptr; |
| 1041 | 1041 | bool any_items_are_range; |
| 1042 | bool is_inline; | |
| 1042 | 1043 | }; |
| 1043 | 1044 | |
| 1044 | 1045 | struct AstNodeSwitchRange { |
src/stage1/parser.cpp+9-3| ... | ... | @@ -2306,7 +2306,7 @@ static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) { |
| 2306 | 2306 | return Optional<PtrIndexPayload>::some(res); |
| 2307 | 2307 | } |
| 2308 | 2308 | |
| 2309 | // SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr | |
| 2309 | // SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrPayload? AssignExpr | |
| 2310 | 2310 | static AstNode *ast_parse_switch_prong(ParseContext *pc) { |
| 2311 | 2311 | AstNode *res = ast_parse_switch_case(pc); |
| 2312 | 2312 | if (res == nullptr) |
| ... | ... | @@ -2331,9 +2331,11 @@ static AstNode *ast_parse_switch_prong(ParseContext *pc) { |
| 2331 | 2331 | // <- SwitchItem (COMMA SwitchItem)* COMMA? |
| 2332 | 2332 | // / KEYWORD_else |
| 2333 | 2333 | static AstNode *ast_parse_switch_case(ParseContext *pc) { |
| 2334 | bool is_inline = eat_token_if(pc, TokenIdKeywordInline) != 0; | |
| 2334 | 2335 | AstNode *first = ast_parse_switch_item(pc); |
| 2335 | 2336 | if (first != nullptr) { |
| 2336 | 2337 | AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeSwitchProng, first); |
| 2338 | res->data.switch_prong.is_inline = is_inline; | |
| 2337 | 2339 | res->data.switch_prong.items.append(first); |
| 2338 | 2340 | res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange; |
| 2339 | 2341 | |
| ... | ... | @@ -2350,9 +2352,13 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) { |
| 2350 | 2352 | } |
| 2351 | 2353 | |
| 2352 | 2354 | TokenIndex else_token = eat_token_if(pc, TokenIdKeywordElse); |
| 2353 | if (else_token != 0) | |
| 2354 | return ast_create_node(pc, NodeTypeSwitchProng, else_token); | |
| 2355 | if (else_token != 0) { | |
| 2356 | AstNode *res = ast_create_node(pc, NodeTypeSwitchProng, else_token); | |
| 2357 | res->data.switch_prong.is_inline = is_inline; | |
| 2358 | return res; | |
| 2359 | } | |
| 2355 | 2360 | |
| 2361 | if (is_inline) pc->current_token -= 1; | |
| 2356 | 2362 | return nullptr; |
| 2357 | 2363 | } |
| 2358 | 2364 |