Skip to content

Commit 3929cac

Browse files
authored
Merge pull request #21257 from mlugg/computed-goto-3
compiler: implement labeled switch/continue
2 parents 7e31804 + 289c704 commit 3929cac

28 files changed

+2690
-824
lines changed

lib/std/zig/Ast.zig

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,14 +1184,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
11841184
n = extra.sentinel;
11851185
},
11861186

1187-
.@"continue" => {
1188-
if (datas[n].lhs != 0) {
1189-
return datas[n].lhs + end_offset;
1190-
} else {
1191-
return main_tokens[n] + end_offset;
1192-
}
1193-
},
1194-
.@"break" => {
1187+
.@"continue", .@"break" => {
11951188
if (datas[n].rhs != 0) {
11961189
n = datas[n].rhs;
11971190
} else if (datas[n].lhs != 0) {
@@ -1895,6 +1888,25 @@ pub fn taggedUnionEnumTag(tree: Ast, node: Node.Index) full.ContainerDecl {
18951888
});
18961889
}
18971890

1891+
pub fn switchFull(tree: Ast, node: Node.Index) full.Switch {
1892+
const data = &tree.nodes.items(.data)[node];
1893+
const main_token = tree.nodes.items(.main_token)[node];
1894+
const switch_token: TokenIndex, const label_token: ?TokenIndex = switch (tree.tokens.items(.tag)[main_token]) {
1895+
.identifier => .{ main_token + 2, main_token },
1896+
.keyword_switch => .{ main_token, null },
1897+
else => unreachable,
1898+
};
1899+
const extra = tree.extraData(data.rhs, Ast.Node.SubRange);
1900+
return .{
1901+
.ast = .{
1902+
.switch_token = switch_token,
1903+
.condition = data.lhs,
1904+
.cases = tree.extra_data[extra.start..extra.end],
1905+
},
1906+
.label_token = label_token,
1907+
};
1908+
}
1909+
18981910
pub fn switchCaseOne(tree: Ast, node: Node.Index) full.SwitchCase {
18991911
const data = &tree.nodes.items(.data)[node];
19001912
const values: *[1]Node.Index = &data.lhs;
@@ -2206,6 +2218,21 @@ fn fullContainerDeclComponents(tree: Ast, info: full.ContainerDecl.Components) f
22062218
return result;
22072219
}
22082220

2221+
fn fullSwitchComponents(tree: Ast, info: full.Switch.Components) full.Switch {
2222+
const token_tags = tree.tokens.items(.tag);
2223+
const tok_i = info.switch_token -| 1;
2224+
var result: full.Switch = .{
2225+
.ast = info,
2226+
.label_token = null,
2227+
};
2228+
if (token_tags[tok_i] == .colon and
2229+
token_tags[tok_i -| 1] == .identifier)
2230+
{
2231+
result.label_token = tok_i - 1;
2232+
}
2233+
return result;
2234+
}
2235+
22092236
fn fullSwitchCaseComponents(tree: Ast, info: full.SwitchCase.Components, node: Node.Index) full.SwitchCase {
22102237
const token_tags = tree.tokens.items(.tag);
22112238
const node_tags = tree.nodes.items(.tag);
@@ -2477,6 +2504,13 @@ pub fn fullContainerDecl(tree: Ast, buffer: *[2]Ast.Node.Index, node: Node.Index
24772504
};
24782505
}
24792506

2507+
pub fn fullSwitch(tree: Ast, node: Node.Index) ?full.Switch {
2508+
return switch (tree.nodes.items(.tag)[node]) {
2509+
.@"switch", .switch_comma => tree.switchFull(node),
2510+
else => null,
2511+
};
2512+
}
2513+
24802514
pub fn fullSwitchCase(tree: Ast, node: Node.Index) ?full.SwitchCase {
24812515
return switch (tree.nodes.items(.tag)[node]) {
24822516
.switch_case_one, .switch_case_inline_one => tree.switchCaseOne(node),
@@ -2829,6 +2863,17 @@ pub const full = struct {
28292863
};
28302864
};
28312865

2866+
pub const Switch = struct {
2867+
ast: Components,
2868+
label_token: ?TokenIndex,
2869+
2870+
pub const Components = struct {
2871+
switch_token: TokenIndex,
2872+
condition: Node.Index,
2873+
cases: []const Node.Index,
2874+
};
2875+
};
2876+
28322877
pub const SwitchCase = struct {
28332878
inline_token: ?TokenIndex,
28342879
/// Points to the first token after the `|`. Will either be an identifier or
@@ -3243,6 +3288,7 @@ pub const Node = struct {
32433288
/// main_token is the `(`.
32443289
async_call_comma,
32453290
/// `switch(lhs) {}`. `SubRange[rhs]`.
3291+
/// `main_token` is the identifier of a preceding label, if any; otherwise `switch`.
32463292
@"switch",
32473293
/// Same as switch except there is known to be a trailing comma
32483294
/// before the final rbrace
@@ -3287,7 +3333,8 @@ pub const Node = struct {
32873333
@"suspend",
32883334
/// `resume lhs`. rhs is unused.
32893335
@"resume",
3290-
/// `continue`. lhs is token index of label if any. rhs is unused.
3336+
/// `continue :lhs rhs`
3337+
/// both lhs and rhs may be omitted.
32913338
@"continue",
32923339
/// `break :lhs rhs`
32933340
/// both lhs and rhs may be omitted.

0 commit comments

Comments
 (0)