authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-13 18:23:35+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-27 18:05:08+03:00
logb4d81857f36a155daa884ba80bfd56c43a182663
tree3cf2a9e926f40fa6326f4a7c9827f286b41526f2
parent8849792789331faec0caaca18822227ecdb9bc62

stage1+2: parse inline switch cases


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 {
643643 n = datas[n].lhs;
644644 }
645645 },
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 },
646653 .switch_case => {
647654 const extra = tree.extraData(datas[n].lhs, Node.SubRange);
648655 assert(extra.end - extra.start > 0);
649656 n = tree.extra_data[extra.start];
650657 },
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 },
651663
652664 .asm_output, .asm_input => {
653665 assert(token_tags[main_tokens[n] - 1] == .l_bracket);
......@@ -763,7 +775,9 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
763775 .ptr_type_bit_range,
764776 .array_type,
765777 .switch_case_one,
778 .switch_case_inline_one,
766779 .switch_case,
780 .switch_case_inline,
767781 .switch_range,
768782 => n = datas[n].rhs,
769783
......@@ -1755,7 +1769,7 @@ pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
17551769 .values = if (data.lhs == 0) values[0..0] else values[0..1],
17561770 .arrow_token = tree.nodes.items(.main_token)[node],
17571771 .target_expr = data.rhs,
1758 });
1772 }, node);
17591773}
17601774
17611775pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
......@@ -1765,7 +1779,7 @@ pub fn switchCase(tree: Ast, node: Node.Index) full.SwitchCase {
17651779 .values = tree.extra_data[extra.start..extra.end],
17661780 .arrow_token = tree.nodes.items(.main_token)[node],
17671781 .target_expr = data.rhs,
1768 });
1782 }, node);
17691783}
17701784
17711785pub fn asmSimple(tree: Ast, node: Node.Index) full.Asm {
......@@ -2038,15 +2052,21 @@ fn fullContainerDecl(tree: Ast, info: full.ContainerDecl.Components) full.Contai
20382052 return result;
20392053}
20402054
2041fn fullSwitchCase(tree: Ast, info: full.SwitchCase.Components) full.SwitchCase {
2055fn fullSwitchCase(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
20422056 const token_tags = tree.tokens.items(.tag);
2057 const node_tags = tree.nodes.items(.tag);
20432058 var result: full.SwitchCase = .{
20442059 .ast = info,
20452060 .payload_token = null,
2061 .inline_token = null,
20462062 };
20472063 if (token_tags[info.arrow_token + 1] == .pipe) {
20482064 result.payload_token = info.arrow_token + 2;
20492065 }
2066 switch (node_tags[node]) {
2067 .switch_case_inline, .switch_case_inline_one => result.inline_token = firstToken(tree, node),
2068 else => {},
2069 }
20502070 return result;
20512071}
20522072
......@@ -2454,6 +2474,7 @@ pub const full = struct {
24542474 };
24552475
24562476 pub const SwitchCase = struct {
2477 inline_token: ?TokenIndex,
24572478 /// Points to the first token after the `|`. Will either be an identifier or
24582479 /// a `*` (with an identifier immediately after it).
24592480 payload_token: ?TokenIndex,
......@@ -2847,9 +2868,13 @@ pub const Node = struct {
28472868 /// `lhs => rhs`. If lhs is omitted it means `else`.
28482869 /// main_token is the `=>`
28492870 switch_case_one,
2871 /// Same ast `switch_case_one` but the case is inline
2872 switch_case_inline_one,
28502873 /// `a, b, c => rhs`. `SubRange[lhs]`.
28512874 /// main_token is the `=>`
28522875 switch_case,
2876 /// Same ast `switch_case` but the case is inline
2877 switch_case_inline,
28532878 /// `lhs...rhs`.
28542879 switch_range,
28552880 /// `while (lhs) rhs`.
lib/std/zig/parse.zig+10-5
......@@ -3100,7 +3100,7 @@ const Parser = struct {
31003100 return identifier;
31013101 }
31023102
3103 /// SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
3103 /// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrPayload? AssignExpr
31043104 /// SwitchCase
31053105 /// <- SwitchItem (COMMA SwitchItem)* COMMA?
31063106 /// / KEYWORD_else
......@@ -3108,6 +3108,8 @@ const Parser = struct {
31083108 const scratch_top = p.scratch.items.len;
31093109 defer p.scratch.shrinkRetainingCapacity(scratch_top);
31103110
3111 const is_inline = p.eatToken(.keyword_inline) != null;
3112
31113113 if (p.eatToken(.keyword_else) == null) {
31123114 while (true) {
31133115 const item = try p.parseSwitchItem();
......@@ -3115,7 +3117,10 @@ const Parser = struct {
31153117 try p.scratch.append(p.gpa, item);
31163118 if (p.eatToken(.comma) == null) break;
31173119 }
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 }
31193124 }
31203125 const arrow_token = try p.expectToken(.equal_angle_bracket_right);
31213126 _ = try p.parsePtrPayload();
......@@ -3123,7 +3128,7 @@ const Parser = struct {
31233128 const items = p.scratch.items[scratch_top..];
31243129 switch (items.len) {
31253130 0 => return p.addNode(.{
3126 .tag = .switch_case_one,
3131 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
31273132 .main_token = arrow_token,
31283133 .data = .{
31293134 .lhs = 0,
......@@ -3131,7 +3136,7 @@ const Parser = struct {
31313136 },
31323137 }),
31333138 1 => return p.addNode(.{
3134 .tag = .switch_case_one,
3139 .tag = if (is_inline) .switch_case_inline_one else .switch_case_one,
31353140 .main_token = arrow_token,
31363141 .data = .{
31373142 .lhs = items[0],
......@@ -3139,7 +3144,7 @@ const Parser = struct {
31393144 },
31403145 }),
31413146 else => return p.addNode(.{
3142 .tag = .switch_case,
3147 .tag = if (is_inline) .switch_case_inline else .switch_case,
31433148 .main_token = arrow_token,
31443149 .data = .{
31453150 .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,
685685 return renderToken(ais, tree, tree.lastToken(node), space); // rbrace
686686 },
687687
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),
690690
691691 .while_simple => return renderWhile(gpa, ais, tree, tree.whileSimple(node), space),
692692 .while_cont => return renderWhile(gpa, ais, tree, tree.whileCont(node), space),
......@@ -1509,6 +1509,11 @@ fn renderSwitchCase(
15091509 break :blk hasComment(tree, tree.firstToken(switch_case.ast.values[0]), switch_case.ast.arrow_token);
15101510 };
15111511
1512 // render inline keyword
1513 if (switch_case.inline_token) |some| {
1514 try renderToken(ais, tree, some, .space);
1515 }
1516
15121517 // Render everything before the arrow
15131518 if (switch_case.ast.values.len == 0) {
15141519 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
386386 .simple_var_decl => unreachable,
387387 .aligned_var_decl => unreachable,
388388 .switch_case => unreachable,
389 .switch_case_inline => unreachable,
389390 .switch_case_one => unreachable,
391 .switch_case_inline_one => unreachable,
390392 .container_field_init => unreachable,
391393 .container_field_align => unreachable,
392394 .container_field => unreachable,
......@@ -600,7 +602,9 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
600602 .@"errdefer" => unreachable, // Handled in `blockExpr`.
601603
602604 .switch_case => unreachable, // Handled in `switchExpr`.
605 .switch_case_inline => unreachable, // Handled in `switchExpr`.
603606 .switch_case_one => unreachable, // Handled in `switchExpr`.
607 .switch_case_inline_one => unreachable, // Handled in `switchExpr`.
604608 .switch_range => unreachable, // Handled in `switchExpr`.
605609
606610 .asm_output => unreachable, // Handled in `asmExpr`.
......@@ -6216,14 +6220,15 @@ fn switchExpr(
62166220 var any_payload_is_ref = false;
62176221 var scalar_cases_len: u32 = 0;
62186222 var multi_cases_len: u32 = 0;
6223 var inline_cases_len: u32 = 0;
62196224 var special_prong: Zir.SpecialProng = .none;
62206225 var special_node: Ast.Node.Index = 0;
62216226 var else_src: ?Ast.TokenIndex = null;
62226227 var underscore_src: ?Ast.TokenIndex = null;
62236228 for (case_nodes) |case_node| {
62246229 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),
62276232 else => unreachable,
62286233 };
62296234 if (case.payload_token) |payload_token| {
......@@ -6318,6 +6323,9 @@ fn switchExpr(
63186323 } else {
63196324 multi_cases_len += 1;
63206325 }
6326 if (case.inline_token != null) {
6327 inline_cases_len += 1;
6328 }
63216329 }
63226330
63236331 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_
84368444 .@"usingnamespace",
84378445 .test_decl,
84388446 .switch_case,
8447 .switch_case_inline,
84398448 .switch_case_one,
8449 .switch_case_inline_one,
84408450 .container_field_init,
84418451 .container_field_align,
84428452 .container_field,
......@@ -8668,7 +8678,9 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
86688678 .@"usingnamespace",
86698679 .test_decl,
86708680 .switch_case,
8681 .switch_case_inline,
86718682 .switch_case_one,
8683 .switch_case_inline_one,
86728684 .container_field_init,
86738685 .container_field_align,
86748686 .container_field,
......@@ -8879,7 +8891,9 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
88798891 .@"usingnamespace",
88808892 .test_decl,
88818893 .switch_case,
8894 .switch_case_inline,
88828895 .switch_case_one,
8896 .switch_case_inline_one,
88838897 .container_field_init,
88848898 .container_field_align,
88858899 .container_field,
src/stage1/all_types.hpp+1
......@@ -1039,6 +1039,7 @@ struct AstNodeSwitchProng {
10391039 AstNode *expr;
10401040 bool var_is_ptr;
10411041 bool any_items_are_range;
1042 bool is_inline;
10421043};
10431044
10441045struct AstNodeSwitchRange {
src/stage1/parser.cpp+9-3
......@@ -2306,7 +2306,7 @@ static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc) {
23062306 return Optional<PtrIndexPayload>::some(res);
23072307}
23082308
2309// SwitchProng <- SwitchCase EQUALRARROW PtrPayload? AssignExpr
2309// SwitchProng <- KEYWORD_inline? SwitchCase EQUALRARROW PtrPayload? AssignExpr
23102310static AstNode *ast_parse_switch_prong(ParseContext *pc) {
23112311 AstNode *res = ast_parse_switch_case(pc);
23122312 if (res == nullptr)
......@@ -2331,9 +2331,11 @@ static AstNode *ast_parse_switch_prong(ParseContext *pc) {
23312331// <- SwitchItem (COMMA SwitchItem)* COMMA?
23322332// / KEYWORD_else
23332333static AstNode *ast_parse_switch_case(ParseContext *pc) {
2334 bool is_inline = eat_token_if(pc, TokenIdKeywordInline) != 0;
23342335 AstNode *first = ast_parse_switch_item(pc);
23352336 if (first != nullptr) {
23362337 AstNode *res = ast_create_node_copy_line_info(pc, NodeTypeSwitchProng, first);
2338 res->data.switch_prong.is_inline = is_inline;
23372339 res->data.switch_prong.items.append(first);
23382340 res->data.switch_prong.any_items_are_range = first->type == NodeTypeSwitchRange;
23392341
......@@ -2350,9 +2352,13 @@ static AstNode *ast_parse_switch_case(ParseContext *pc) {
23502352 }
23512353
23522354 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 }
23552360
2361 if (is_inline) pc->current_token -= 1;
23562362 return nullptr;
23572363}
23582364