parser: port full "while" and "for" tests
Port tests: - "while" (full test with all variants) - "for" (full test with all variants including testTransform) Fix in parser.c: - comptime var decl: don't wrap in comptime node (renderer detects comptime from token positions) - forPrefix: handle trailing comma in input list and capture list Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
19
parser.c
19
parser.c
@@ -1335,6 +1335,8 @@ static uint32_t forPrefix(Parser* p) {
|
||||
SLICE_APPEND(AstNodeIndex, &p->scratch, input);
|
||||
if (p->token_tags[p->tok_i] == TOKEN_COMMA) {
|
||||
p->tok_i++;
|
||||
if (eatToken(p, TOKEN_R_PAREN) != null_token)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
expectToken(p, TOKEN_R_PAREN);
|
||||
@@ -1349,6 +1351,8 @@ static uint32_t forPrefix(Parser* p) {
|
||||
expectToken(p, TOKEN_IDENTIFIER);
|
||||
if (p->token_tags[p->tok_i] == TOKEN_COMMA) {
|
||||
p->tok_i++;
|
||||
if (eatToken(p, TOKEN_PIPE) != null_token)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
expectToken(p, TOKEN_PIPE);
|
||||
@@ -2660,10 +2664,21 @@ static AstNodeIndex expectStatement(Parser* p, bool allow_defer_var) {
|
||||
.data = { .lhs = block, .rhs = 0 },
|
||||
});
|
||||
}
|
||||
// comptime var decl or expression — the result needs to be
|
||||
// wrapped in a comptime node
|
||||
// comptime var decl or expression
|
||||
if (allow_defer_var) {
|
||||
// Pass through to expectVarDeclExprStatement.
|
||||
// For var decls, the comptime prefix is detected from token
|
||||
// positions by the renderer (no wrapping needed).
|
||||
// For expressions, the result is wrapped in a comptime node.
|
||||
const AstNodeIndex inner = expectVarDeclExprStatement(p);
|
||||
const AstNodeTag inner_tag = p->nodes.tags[inner];
|
||||
if (inner_tag == AST_NODE_SIMPLE_VAR_DECL
|
||||
|| inner_tag == AST_NODE_ALIGNED_VAR_DECL
|
||||
|| inner_tag == AST_NODE_LOCAL_VAR_DECL
|
||||
|| inner_tag == AST_NODE_GLOBAL_VAR_DECL
|
||||
|| inner_tag == AST_NODE_ASSIGN_DESTRUCTURE) {
|
||||
return inner;
|
||||
}
|
||||
return addNode(&p->nodes,
|
||||
(AstNodeItem) {
|
||||
.tag = AST_NODE_COMPTIME,
|
||||
|
||||
188
parser_test.zig
188
parser_test.zig
@@ -3778,6 +3778,194 @@ test "zig fmt: switch" {
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: while" {
|
||||
try testCanonical(
|
||||
\\test "while" {
|
||||
\\ while (10 < 1) unreachable;
|
||||
\\
|
||||
\\ while (10 < 1) unreachable else unreachable;
|
||||
\\
|
||||
\\ while (10 < 1) {
|
||||
\\ unreachable;
|
||||
\\ }
|
||||
\\
|
||||
\\ while (10 < 1)
|
||||
\\ unreachable;
|
||||
\\
|
||||
\\ var i: usize = 0;
|
||||
\\ while (i < 10) : (i += 1) {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ i = 0;
|
||||
\\ while (i < 10) : (i += 1)
|
||||
\\ continue;
|
||||
\\
|
||||
\\ i = 0;
|
||||
\\ var j: usize = 0;
|
||||
\\ while (i < 10) : ({
|
||||
\\ i += 1;
|
||||
\\ j += 1;
|
||||
\\ }) continue;
|
||||
\\
|
||||
\\ while (i < 10) : ({
|
||||
\\ i += 1;
|
||||
\\ j += 1;
|
||||
\\ }) {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ var a: ?u8 = 2;
|
||||
\\ while (a) |v| : (a = null) {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ while (a) |v| : (a = null)
|
||||
\\ continue;
|
||||
\\
|
||||
\\ while (a) |v| : (a = null)
|
||||
\\ continue
|
||||
\\ else
|
||||
\\ unreachable;
|
||||
\\
|
||||
\\ for (&[_]u8{}) |v| {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ while (a) |v| : (a = null)
|
||||
\\ unreachable;
|
||||
\\
|
||||
\\ label: while (10 < 0) {
|
||||
\\ unreachable;
|
||||
\\ }
|
||||
\\
|
||||
\\ const res = while (0 < 10) {
|
||||
\\ break 7;
|
||||
\\ } else {
|
||||
\\ unreachable;
|
||||
\\ };
|
||||
\\
|
||||
\\ const res = while (0 < 10)
|
||||
\\ break 7
|
||||
\\ else
|
||||
\\ unreachable;
|
||||
\\
|
||||
\\ var a: anyerror!u8 = 0;
|
||||
\\ while (a) |v| {
|
||||
\\ a = error.Err;
|
||||
\\ } else |err| {
|
||||
\\ i = 1;
|
||||
\\ }
|
||||
\\
|
||||
\\ comptime var k: usize = 0;
|
||||
\\ inline while (i < 10) : (i += 1)
|
||||
\\ j += 2;
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: for" {
|
||||
try testCanonical(
|
||||
\\test "for" {
|
||||
\\ for (a) |v| {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ for (a) |v| continue;
|
||||
\\
|
||||
\\ for (a) |v| continue else return;
|
||||
\\
|
||||
\\ for (a) |v| {
|
||||
\\ continue;
|
||||
\\ } else return;
|
||||
\\
|
||||
\\ for (a) |v| continue else {
|
||||
\\ return;
|
||||
\\ }
|
||||
\\
|
||||
\\ for (a) |v|
|
||||
\\ continue
|
||||
\\ else
|
||||
\\ return;
|
||||
\\
|
||||
\\ for (a) |v|
|
||||
\\ continue;
|
||||
\\
|
||||
\\ for (a) |*v|
|
||||
\\ continue;
|
||||
\\
|
||||
\\ for (a, 0..) |v, i| {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\
|
||||
\\ for (a, 0..) |v, i|
|
||||
\\ continue;
|
||||
\\
|
||||
\\ for (a) |b| switch (b) {
|
||||
\\ c => {},
|
||||
\\ d => {},
|
||||
\\ };
|
||||
\\
|
||||
\\ const res = for (a, 0..) |v, i| {
|
||||
\\ break v;
|
||||
\\ } else {
|
||||
\\ unreachable;
|
||||
\\ };
|
||||
\\
|
||||
\\ var num: usize = 0;
|
||||
\\ inline for (a, 0..1) |v, i| {
|
||||
\\ num += v;
|
||||
\\ num += i;
|
||||
\\ }
|
||||
\\
|
||||
\\ for (a, b) |
|
||||
\\ long_name,
|
||||
\\ another_long_name,
|
||||
\\ | {
|
||||
\\ continue;
|
||||
\\ }
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
try testTransform(
|
||||
\\test "fix for" {
|
||||
\\ for (a) |x|
|
||||
\\ f(x) else continue;
|
||||
\\}
|
||||
\\
|
||||
,
|
||||
\\test "fix for" {
|
||||
\\ for (a) |x|
|
||||
\\ f(x)
|
||||
\\ else
|
||||
\\ continue;
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
|
||||
try testTransform(
|
||||
\\test "fix for" {
|
||||
\\ for (a, b, c,) |long, another, third,| {}
|
||||
\\}
|
||||
\\
|
||||
,
|
||||
\\test "fix for" {
|
||||
\\ for (
|
||||
\\ a,
|
||||
\\ b,
|
||||
\\ c,
|
||||
\\ ) |
|
||||
\\ long,
|
||||
\\ another,
|
||||
\\ third,
|
||||
\\ | {}
|
||||
\\}
|
||||
\\
|
||||
);
|
||||
}
|
||||
|
||||
test "zig fmt: for if" {
|
||||
try testCanonical(
|
||||
\\test {
|
||||
|
||||
Reference in New Issue
Block a user