AstGen: implement await and resume

based on @Vexu's code from before
This commit is contained in:
Andrew Kelley 2021-04-24 14:39:44 -07:00
parent e86cee258c
commit 1592206965
3 changed files with 52 additions and 2 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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,