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