Commit cb3a818699

Andrew Kelley <andrew@ziglang.org>
2020-02-15 21:05:31
zig fmt: support `noasync await`
1 parent 72805fd
Changed files (5)
lib/std/zig/ast.zig
@@ -1564,7 +1564,9 @@ pub const Node = struct {
         pub const Op = union(enum) {
             AddressOf,
             ArrayType: ArrayInfo,
-            Await,
+            Await: struct {
+                noasync_token: ?TokenIndex = null,
+            },
             BitNot,
             BoolNot,
             Cancel,
lib/std/zig/parse.zig
@@ -1129,7 +1129,7 @@ fn parseErrorUnionExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
 ///      / KEYWORD_noasync PrimaryTypeExpr SuffixOp* FnCallArguments
 ///      / PrimaryTypeExpr (SuffixOp / FnCallArguments)*
 fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
-    var maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);
+    const maybe_async = eatAnnotatedToken(it, .Keyword_async) orelse eatAnnotatedToken(it, .Keyword_noasync);
     if (maybe_async) |async_token| {
         const token_fn = eatToken(it, .Keyword_fn);
         if (async_token.ptr.id == .Keyword_async and token_fn != null) {
@@ -2179,7 +2179,19 @@ fn parsePrefixOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
         .MinusPercent => ops{ .NegationWrap = {} },
         .Ampersand => ops{ .AddressOf = {} },
         .Keyword_try => ops{ .Try = {} },
-        .Keyword_await => ops{ .Await = {} },
+        .Keyword_await => ops{ .Await = .{} },
+        .Keyword_noasync => if (eatToken(it, .Keyword_await)) |await_tok| {
+            const node = try arena.create(Node.PrefixOp);
+            node.* = Node.PrefixOp{
+                .op_token = await_tok,
+                .op = .{ .Await = .{ .noasync_token = token.index } },
+                .rhs = undefined, // set by caller
+            };
+            return &node.base;
+        } else {
+            putBackToken(it, token.index);
+            return null;
+        },
         else => {
             putBackToken(it, token.index);
             return null;
lib/std/zig/parser_test.zig
@@ -1,3 +1,12 @@
+test "zig fmt: noasync await" {
+    try testCanonical(
+        \\fn foo() void {
+        \\    x = noasync await y;
+        \\}
+        \\
+    );
+}
+
 test "zig fmt: trailing comma in container declaration" {
     try testCanonical(
         \\const X = struct { foo: i32 };
lib/std/zig/render.zig
@@ -584,12 +584,18 @@ fn renderExpression(
                 },
 
                 .Try,
-                .Await,
                 .Cancel,
                 .Resume,
                 => {
                     try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
                 },
+
+                .Await => |await_info| {
+                    if (await_info.noasync_token) |tok| {
+                        try renderToken(tree, stream, tok, indent, start_col, Space.Space);
+                    }
+                    try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.Space);
+                },
             }
 
             return renderExpression(allocator, stream, tree, indent, start_col, prefix_op_node.rhs, space);
test/stage1/behavior/async_fn.zig
@@ -1510,3 +1510,20 @@ test "take address of temporary async frame" {
     };
     S.doTheTest();
 }
+
+test "noasync await" {
+    const S = struct {
+        fn doTheTest() void {
+            var frame = async foo(false);
+            expect(noasync await frame == 42);
+        }
+
+        fn foo(want_suspend: bool) i32 {
+            if (want_suspend) {
+                suspend;
+            }
+            return 42;
+        }
+    };
+    S.doTheTest();
+}