Commit 895f262a55
Changed files (7)
src
test
src/parser.cpp
@@ -651,37 +651,29 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
SuspendExpression(body) = "suspend" option( body )
*/
static AstNode *ast_parse_suspend_block(ParseContext *pc, size_t *token_index, bool mandatory) {
- size_t orig_token_index = *token_index;
- Token *token = &pc->tokens->at(*token_index);
- Token *suspend_token = nullptr;
+ Token *suspend_token = &pc->tokens->at(*token_index);
- if (token->id == TokenIdKeywordSuspend) {
+ if (suspend_token->id == TokenIdKeywordSuspend) {
*token_index += 1;
- suspend_token = token;
- token = &pc->tokens->at(*token_index);
} else if (mandatory) {
- ast_expect_token(pc, token, TokenIdKeywordSuspend);
+ ast_expect_token(pc, suspend_token, TokenIdKeywordSuspend);
zig_unreachable();
} else {
return nullptr;
}
- //guessing that semicolon is checked elsewhere?
- if (token->id != TokenIdLBrace) {
- if (mandatory) {
- ast_expect_token(pc, token, TokenIdLBrace);
- zig_unreachable();
- } else {
- *token_index = orig_token_index;
- return nullptr;
- }
+ Token *lbrace = &pc->tokens->at(*token_index);
+ if (lbrace->id == TokenIdLBrace) {
+ AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
+ node->data.suspend.block = ast_parse_block(pc, token_index, true);
+ return node;
+ } else if (mandatory) {
+ ast_expect_token(pc, lbrace, TokenIdLBrace);
+ zig_unreachable();
+ } else {
+ *token_index -= 1;
+ return nullptr;
}
-
- //Expect that we have a block;
- AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
- node->data.suspend.block = ast_parse_block(pc, token_index, true);
-
- return node;
}
/*
std/zig/ast.zig
@@ -1778,19 +1778,12 @@ pub const Node = struct {
pub const Suspend = struct {
base: Node,
- label: ?TokenIndex,
suspend_token: TokenIndex,
- payload: ?*Node,
body: ?*Node,
pub fn iterate(self: *Suspend, index: usize) ?*Node {
var i = index;
- if (self.payload) |payload| {
- if (i < 1) return payload;
- i -= 1;
- }
-
if (self.body) |body| {
if (i < 1) return body;
i -= 1;
@@ -1800,7 +1793,6 @@ pub const Node = struct {
}
pub fn firstToken(self: *Suspend) TokenIndex {
- if (self.label) |label| return label;
return self.suspend_token;
}
@@ -1809,10 +1801,6 @@ pub const Node = struct {
return body.lastToken();
}
- if (self.payload) |payload| {
- return payload.lastToken();
- }
-
return self.suspend_token;
}
};
std/zig/parse.zig
@@ -852,19 +852,6 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
}) catch unreachable;
continue;
},
- Token.Id.Keyword_suspend => {
- const node = try arena.create(ast.Node.Suspend{
- .base = ast.Node{ .id = ast.Node.Id.Suspend },
- .label = ctx.label,
- .suspend_token = token_index,
- .payload = null,
- .body = null,
- });
- ctx.opt_ctx.store(&node.base);
- stack.append(State{ .SuspendBody = node }) catch unreachable;
- try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
- continue;
- },
Token.Id.Keyword_inline => {
stack.append(State{
.Inline = InlineCtx{
@@ -1415,10 +1402,21 @@ pub fn parse(allocator: *mem.Allocator, source: []const u8) !ast.Tree {
},
State.SuspendBody => |suspend_node| {
- if (suspend_node.payload != null) {
- try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });
+ const token = nextToken(&tok_it, &tree);
+ switch (token.ptr.id) {
+ Token.Id.Semicolon => {
+ prevToken(&tok_it, &tree);
+ continue;
+ },
+ Token.Id.LBrace => {
+ prevToken(&tok_it, &tree);
+ try stack.append(State{ .AssignmentExpressionBegin = OptionalCtx{ .RequiredNull = &suspend_node.body } });
+ continue;
+ },
+ else => {
+ ((try tree.errors.addOne())).* = Error{ .InvalidToken = Error.InvalidToken{ .token = token.index } };
+ },
}
- continue;
},
State.AsyncAllocator => |async_node| {
if (eatToken(&tok_it, &tree, Token.Id.AngleBracketLeft) == null) {
@@ -3086,15 +3084,12 @@ fn parseBlockExpr(stack: *std.ArrayList(State), arena: *mem.Allocator, ctx: *con
Token.Id.Keyword_suspend => {
const node = try arena.create(ast.Node.Suspend{
.base = ast.Node{ .id = ast.Node.Id.Suspend },
- .label = null,
.suspend_token = token_index,
- .payload = null,
.body = null,
});
ctx.store(&node.base);
stack.append(State{ .SuspendBody = node }) catch unreachable;
- try stack.append(State{ .Payload = OptionalCtx{ .Optional = &node.payload } });
return true;
},
Token.Id.Keyword_if => {
std/zig/parser_test.zig
@@ -898,11 +898,11 @@ test "zig fmt: union(enum(u32)) with assigned enum values" {
);
}
-test "zig fmt: labeled suspend" {
+test "zig fmt: resume from suspend block" {
try testCanonical(
\\fn foo() void {
- \\ s: suspend |p| {
- \\ break :s;
+ \\ suspend {
+ \\ resume @handle();
\\ }
\\}
\\
std/zig/render.zig
@@ -323,21 +323,7 @@ fn renderExpression(
ast.Node.Id.Suspend => {
const suspend_node = @fieldParentPtr(ast.Node.Suspend, "base", base);
- if (suspend_node.label) |label| {
- try renderToken(tree, stream, label, indent, start_col, Space.None);
- try renderToken(tree, stream, tree.nextToken(label), indent, start_col, Space.Space);
- }
-
- if (suspend_node.payload) |payload| {
- if (suspend_node.body) |body| {
- try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
- try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
- return renderExpression(allocator, stream, tree, indent, start_col, body, space);
- } else {
- try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
- return renderExpression(allocator, stream, tree, indent, start_col, payload, space);
- }
- } else if (suspend_node.body) |body| {
+ if (suspend_node.body) |body| {
try renderToken(tree, stream, suspend_node.suspend_token, indent, start_col, Space.Space);
return renderExpression(allocator, stream, tree, indent, start_col, body, space);
} else {
test/cases/coroutines.zig
@@ -256,19 +256,3 @@ async fn testBreakFromSuspend(my_result: *i32) void {
suspend;
my_result.* += 1;
}
-
-test "suspend resume @handle()" {
- var buf: [500]u8 = undefined;
- var a = &std.heap.FixedBufferAllocator.init(buf[0..]).allocator;
- var my_result: i32 = 1;
- const p = try async<a> testBreakFromSuspend(&my_result);
- std.debug.assert(my_result == 2);
-}
-async fn testSuspendResumeAtHandle() void {
- suspend {
- resume @handle();
- }
- my_result.* += 1;
- suspend;
- my_result.* += 1;
-}
\ No newline at end of file
test/compile_errors.zig
@@ -1,6 +1,27 @@
const tests = @import("tests.zig");
pub fn addCases(cases: *tests.CompileErrorContext) void {
+ cases.add(
+ "@handle() called outside of function definition",
+ \\var handle_undef: promise = undefined;
+ \\var handle_dummy: promise = @handle();
+ \\export fn entry() bool {
+ \\ return handle_undef == handle_dummy;
+ \\}
+ ,
+ ".tmp_source.zig:2:29: error: @handle() called outside of function definition",
+ );
+
+ cases.add(
+ "@handle() in non-async function",
+ \\export fn entry() bool {
+ \\ var handle_undef: promise = undefined;
+ \\ return handle_undef == @handle();
+ \\}
+ ,
+ ".tmp_source.zig:3:28: error: @handle() in non-async function",
+ );
+
cases.add(
"while loop body expression ignored",
\\fn returns() usize {
@@ -4738,34 +4759,4 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
".tmp_source.zig:3:36: error: @ArgType could not resolve the type of arg 0 because 'fn(var)var' is generic",
);
-
- cases.add(
- "@handle() called outside of function definition",
- \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
- \\ @import("std").os.exit(126);
- \\}
- \\
- \\var handle_undef: promise = undefined;
- \\var handle_dummy: promise = @handle();
- \\
- \\pub fn main() void {
- \\ if (handle_undef == handle_dummy) return 0;
- \\}
- ,
- ".tmp_source.zig:6:29: error: @handle() called outside of function definition",
- );
-
- cases.add(
- "@handle() in non-async function",
- \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
- \\ @import("std").os.exit(126);
- \\}
- \\
- \\pub fn main() void {
- \\ var handle_undef: promise = undefined;
- \\ if (handle_undef == @handle()) return 0;
- \\}
- ,
- ".tmp_source.zig:7:25: error: @handle() in non-async function",
- );
}