Skip to content

Commit b4d8185

Browse files
committed
stage1+2: parse inline switch cases
1 parent 8849792 commit b4d8185

File tree

6 files changed

+71
-15
lines changed

6 files changed

+71
-15
lines changed

lib/std/zig/Ast.zig

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

17611775
pub 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

17711785
pub 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

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 {
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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3100,46 +3100,51 @@ 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
31073107
fn parseSwitchProng(p: *Parser) !Node.Index {
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();
31143116
if (item == 0) break;
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();
31223127

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,
31303135
.rhs = try p.expectAssignExpr(),
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],
31383143
.rhs = try p.expectAssignExpr(),
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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

10441045
struct AstNodeSwitchRange {

src/stage1/parser.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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
23102310
static 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
23332333
static 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

0 commit comments

Comments
 (0)