Commit 1592206965

Andrew Kelley <andrew@ziglang.org>
2021-04-24 23:39:44
AstGen: implement await and resume
based on @Vexu's code from before
1 parent e86cee2
Changed files (3)
src/AstGen.zig
@@ -959,7 +959,19 @@ pub fn awaitExpr(
     node: ast.Node.Index,
 ) InnerError!Zir.Inst.Ref {
     const astgen = gz.astgen;
-    return astgen.failNode(node, "TODO AstGen awaitExpr", .{});
+    const tree = &astgen.file.tree;
+    const node_datas = tree.nodes.items(.data);
+    const rhs_node = node_datas[node].lhs;
+
+    if (gz.suspend_node != 0) {
+        return astgen.failNodeNotes(node, "cannot await inside suspend block", .{}, &[_]u32{
+            try astgen.errNoteNode(gz.suspend_node, "suspend block here", .{}),
+        });
+    }
+    const operand = try expr(gz, scope, .none, rhs_node);
+    const tag: Zir.Inst.Tag = if (gz.nosuspend_node != 0) .await_nosuspend else .@"await";
+    const result = try gz.addUnNode(tag, operand, node);
+    return rvalue(gz, scope, rl, result, node);
 }
 
 pub fn resumeExpr(
@@ -969,7 +981,12 @@ pub fn resumeExpr(
     node: ast.Node.Index,
 ) InnerError!Zir.Inst.Ref {
     const astgen = gz.astgen;
-    return astgen.failNode(node, "TODO AstGen resumeExpr", .{});
+    const tree = &astgen.file.tree;
+    const node_datas = tree.nodes.items(.data);
+    const rhs_node = node_datas[node].lhs;
+    const operand = try expr(gz, scope, .none, rhs_node);
+    const result = try gz.addUnNode(.@"resume", operand, node);
+    return rvalue(gz, scope, rl, result, node);
 }
 
 pub fn fnProtoExpr(
@@ -2005,6 +2022,9 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
             .memset,
             .builtin_async_call,
             .c_import,
+            .@"resume",
+            .@"await",
+            .await_nosuspend,
             .extended,
             => break :b false,
 
src/Sema.zig
@@ -317,6 +317,9 @@ pub fn analyzeBody(
             .memcpy                       => try sema.zirMemcpy(block, inst),
             .memset                       => try sema.zirMemset(block, inst),
             .builtin_async_call           => try sema.zirBuiltinAsyncCall(block, inst),
+            .@"resume"                    => try sema.zirResume(block, inst),
+            .@"await"                     => try sema.zirAwait(block, inst, false),
+            .await_nosuspend              => try sema.zirAwait(block, inst, true),
             .extended                     => try sema.zirExtended(block, inst),
 
             .sqrt  => try sema.zirUnaryMath(block, inst),
@@ -5413,6 +5416,23 @@ fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) I
     return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinAsyncCall", .{});
 }
 
+fn zirResume(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
+    const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+    const src = inst_data.src();
+    return sema.mod.fail(&block.base, src, "TODO: Sema.zirResume", .{});
+}
+
+fn zirAwait(
+    sema: *Sema,
+    block: *Scope.Block,
+    inst: Zir.Inst.Index,
+    is_nosuspend: bool,
+) InnerError!*Inst {
+    const inst_data = sema.code.instructions.items(.data)[inst].un_node;
+    const src = inst_data.src();
+    return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{});
+}
+
 fn zirFuncExtended(
     sema: *Sema,
     block: *Scope.Block,
src/Zir.zig
@@ -936,6 +936,10 @@ pub const Inst = struct {
         /// Uses the `un_node` field. The AST node is the var decl.
         resolve_inferred_alloc,
 
+        @"resume",
+        @"await",
+        await_nosuspend,
+
         /// The ZIR instruction tag is one of the `Extended` ones.
         /// Uses the `extended` union field.
         extended,
@@ -1185,6 +1189,9 @@ pub const Inst = struct {
                 .memset,
                 .builtin_async_call,
                 .c_import,
+                .@"resume",
+                .@"await",
+                .await_nosuspend,
                 .extended,
                 => false,
 
@@ -2416,6 +2423,9 @@ const Writer = struct {
             .byte_swap,
             .bit_reverse,
             .elem_type,
+            .@"resume",
+            .@"await",
+            .await_nosuspend,
             => try self.writeUnNode(stream, inst),
 
             .ref,