Commit 895f262a55

Andrew Kelley <superjoe30@gmail.com>
2018-08-02 20:15:31
pull request fixups
* clean up parser code * fix stage2 parse and render code * remove redundant test * make stage1 compile tests leaner
1 parent 44fd304
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",
-    );
 }