From e79c913cbcb03834fcc04e2258ed5da7d533c9db Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 27 Jul 2018 19:16:31 +0900
Subject: [PATCH 01/39] src/all_types.hpp: add enums for Handle Builtin;
Tracking Issue #1296 ;
---
src/all_types.hpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 2f09e70301..f03a250aea 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1358,6 +1358,7 @@ enum BuiltinFnId {
BuiltinFnIdBreakpoint,
BuiltinFnIdReturnAddress,
BuiltinFnIdFrameAddress,
+ BuiltinFnIdHandle,
BuiltinFnIdEmbedFile,
BuiltinFnIdCmpxchgWeak,
BuiltinFnIdCmpxchgStrong,
@@ -2076,6 +2077,7 @@ enum IrInstructionId {
IrInstructionIdBreakpoint,
IrInstructionIdReturnAddress,
IrInstructionIdFrameAddress,
+ IrInstructionIdHandle,
IrInstructionIdAlignOf,
IrInstructionIdOverflowOp,
IrInstructionIdTestErr,
@@ -2793,6 +2795,10 @@ struct IrInstructionFrameAddress {
IrInstruction base;
};
+struct IrInstructionHandle {
+ IrInstruction base;
+};
+
enum IrOverflowOp {
IrOverflowOpAdd,
IrOverflowOpSub,
From a9ea22d4f9816998cccfca4df2ef56d5069e1814 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 27 Jul 2018 19:17:38 +0900
Subject: [PATCH 02/39] src/ir.cpp: wire-up IR for handle builtin;
Tracking Issue #1296 ;
---
src/ir.cpp | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index 699baa152e..50c8c70290 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -580,6 +580,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFrameAddress *)
return IrInstructionIdFrameAddress;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionHandle *) {
+ return IrInstructionIdHandle;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionAlignOf *) {
return IrInstructionIdAlignOf;
}
@@ -2240,6 +2244,17 @@ static IrInstruction *ir_build_frame_address_from(IrBuilder *irb, IrInstruction
return new_instruction;
}
+static IrInstruction *ir_build_handle(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+ IrInstructionHandle *instruction = ir_build_instruction(irb, scope, source_node);
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_handle_from(IrBuilder *irb, IrInstruction *old_instruction) {
+ IrInstruction *new_instruction = ir_build_handle(irb, old_instruction->scope, old_instruction->source_node);
+ ir_link_new_instruction(new_instruction, old_instruction);
+ return new_instruction;
+}
+
static IrInstruction *ir_build_overflow_op(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrOverflowOp op, IrInstruction *type_value, IrInstruction *op1, IrInstruction *op2,
IrInstruction *result_ptr, TypeTableEntry *result_ptr_type)
@@ -4475,6 +4490,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return ir_lval_wrap(irb, scope, ir_build_return_address(irb, scope, node), lval);
case BuiltinFnIdFrameAddress:
return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
+ case BuiltinFnIdHandle:
+ return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);
case BuiltinFnIdAlignOf:
{
AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
@@ -19007,6 +19024,13 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn
return u8_ptr_const;
}
+static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {
+ ir_build_handle_from(&ira->new_irb, &instruction->base);
+
+ TypeTableEntry *promise_type = get_promise_type(ira->codegen, nullptr);
+ return promise_type;
+}
+
static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
IrInstruction *type_value = instruction->type_value->other;
if (type_is_invalid(type_value->value.type))
@@ -20982,6 +21006,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_return_address(ira, (IrInstructionReturnAddress *)instruction);
case IrInstructionIdFrameAddress:
return ir_analyze_instruction_frame_address(ira, (IrInstructionFrameAddress *)instruction);
+ case IrInstructionIdHandle:
+ return ir_analyze_instruction_handle(ira, (IrInstructionHandle *)instruction);
case IrInstructionIdAlignOf:
return ir_analyze_instruction_align_of(ira, (IrInstructionAlignOf *)instruction);
case IrInstructionIdOverflowOp:
@@ -21274,6 +21300,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdAlignOf:
case IrInstructionIdReturnAddress:
case IrInstructionIdFrameAddress:
+ case IrInstructionIdHandle:
case IrInstructionIdTestErr:
case IrInstructionIdUnwrapErrCode:
case IrInstructionIdOptionalWrap:
From cd18186715bf532715c03d8e67096606fe0f2bee Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 27 Jul 2018 19:18:29 +0900
Subject: [PATCH 03/39] src/codegen.cpp: base handle builtin on
`@frameAddress()`;
Tracking Issue #1296 ;
---
src/codegen.cpp | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 7420da9797..336aded82c 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4146,6 +4146,15 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
return LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, "");
}
+static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
+ IrInstructionHandle *instruction)
+{
+ // @andrewrk, not sure what to place here ?
+ // `get_promise_frame_type` ?
+ LLVMValueRef handle = LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+ return LLVMBuildRet(g->builder, handle);
+}
+
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
TypeTableEntry *int_type = instruction->result_ptr_type;
assert(int_type->id == TypeTableEntryIdInt);
@@ -4910,6 +4919,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_return_address(g, executable, (IrInstructionReturnAddress *)instruction);
case IrInstructionIdFrameAddress:
return ir_render_frame_address(g, executable, (IrInstructionFrameAddress *)instruction);
+ case IrInstructionIdHandle:
+ return ir_render_handle(g, executable, (IrInstructionHandle *)instruction);
case IrInstructionIdOverflowOp:
return ir_render_overflow_op(g, executable, (IrInstructionOverflowOp *)instruction);
case IrInstructionIdTestErr:
@@ -6344,6 +6355,7 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdBreakpoint, "breakpoint", 0);
create_builtin_fn(g, BuiltinFnIdReturnAddress, "returnAddress", 0);
create_builtin_fn(g, BuiltinFnIdFrameAddress, "frameAddress", 0);
+ create_builtin_fn(g, BuiltinFnIdHandle, "handle", 0);
create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy", 3);
create_builtin_fn(g, BuiltinFnIdMemset, "memset", 3);
create_builtin_fn(g, BuiltinFnIdSizeof, "sizeOf", 1);
From da5f3d5c4c79b1d0d0919a0226f5304081b2f049 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 27 Jul 2018 19:19:16 +0900
Subject: [PATCH 04/39] src/ir_print.cpp: support `@handle()`;
Tracking Issue #1296 ;
---
src/ir_print.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 127afa94a5..77c7ef47b6 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -791,6 +791,10 @@ static void ir_print_frame_address(IrPrint *irp, IrInstructionFrameAddress *inst
fprintf(irp->f, "@frameAddress()");
}
+static void ir_print_handle(IrPrint *irp, IrInstructionHandle *instruction) {
+ fprintf(irp->f, "@handle()");
+}
+
static void ir_print_return_address(IrPrint *irp, IrInstructionReturnAddress *instruction) {
fprintf(irp->f, "@returnAddress()");
}
@@ -1556,6 +1560,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdFrameAddress:
ir_print_frame_address(irp, (IrInstructionFrameAddress *)instruction);
break;
+ case IrInstructionIdHandle:
+ ir_print_handle(irp, (IrInstructionHandle *)instruction);
+ break;
case IrInstructionIdAlignOf:
ir_print_align_of(irp, (IrInstructionAlignOf *)instruction);
break;
From 9366a58bdd91a8b5e7bc7d4babb6f91b989769db Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 27 Jul 2018 19:19:47 +0900
Subject: [PATCH 05/39] test/cases/couroutines.zig: test @handle();
Tracking Issue #1296 ;
---
test/cases/coroutines.zig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 72a4ed0b38..53c5c3f906 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -66,6 +66,11 @@ async fn testSuspendBlock() void {
comptime assert(@typeOf(p) == promise->void);
a_promise = p;
}
+
+ //Test to make sure that @handle() works as advertised (issue #1296)
+ //var our_handle: promise = @handle();
+ assert( a_promise == @handle() );
+
result = true;
}
From a2e5691228c61e5c56220fc8f5f72e47b0611000 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 11:46:31 +0900
Subject: [PATCH 06/39] src/codegen.cpp: return null if calling convention is
not async;
Tracking Issue #1296 ;
---
src/codegen.cpp | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 336aded82c..cbd1955839 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4149,9 +4149,15 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
IrInstructionHandle *instruction)
{
- // @andrewrk, not sure what to place here ?
- // `get_promise_frame_type` ?
- LLVMValueRef handle = LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+
+ bool is_async = executable->fn_entry != nullptr &&
+ executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
+
+ if (!is_async || !executable->coro_handle) {
+ return LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+ }
+
+ LLVMValueRef handle = ir_llvm_value(g, executable->coro_handle);
return LLVMBuildRet(g->builder, handle);
}
From 81f463626ad09dd09e525cda140fb63baf11bc73 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 14:13:26 +0900
Subject: [PATCH 07/39] src/codegen.cpp: add/throw error for @handle() in a non
async context;
Tracking Issue #1296 ;
I removed/commented-out the assert checking for no errors since we now have some errors rendered.
---
src/codegen.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index cbd1955839..43e2a0b694 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4154,6 +4154,7 @@ static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
if (!is_async || !executable->coro_handle) {
+ add_node_error(g, instruction->base.source_node, buf_sprintf("@handle() in non-async function"));
return LLVMConstNull(g->builtin_types.entry_promise->type_ref);
}
@@ -6022,7 +6023,8 @@ static void do_code_gen(CodeGen *g) {
ir_render(g, fn_table_entry);
}
- assert(!g->errors.length);
+
+ //assert(!g->errors.length);
if (buf_len(&g->global_asm) != 0) {
LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
From 0ee65025623c0440ed655d68b579f17e6d6e5f5c Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 15:20:56 +0900
Subject: [PATCH 08/39] src/codegen.cpp: remove `add_node_error` from
`ir_render_handle`;
Tracking Issue #1296 ;
Thanks @andrewrk ;
---
src/codegen.cpp | 12 +-----------
test/cases/coroutines.zig | 3 +++
2 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 43e2a0b694..8a18a3f8dd 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4149,17 +4149,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
IrInstructionHandle *instruction)
{
-
- bool is_async = executable->fn_entry != nullptr &&
- executable->fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
-
- if (!is_async || !executable->coro_handle) {
- add_node_error(g, instruction->base.source_node, buf_sprintf("@handle() in non-async function"));
- return LLVMConstNull(g->builtin_types.entry_promise->type_ref);
- }
-
- LLVMValueRef handle = ir_llvm_value(g, executable->coro_handle);
- return LLVMBuildRet(g->builder, handle);
+ return LLVMConstNull(g->builtin_types.entry_promise->type_ref);
}
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 53c5c3f906..deb4aa1b24 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -57,6 +57,9 @@ test "coroutine suspend with block" {
resume a_promise;
std.debug.assert(result);
cancel p;
+
+ assert( @handle() );
+
}
var a_promise: promise = undefined;
From db362bec185d2eeb5a4dd018deb2a988479f0f1a Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 15:22:00 +0900
Subject: [PATCH 09/39] src/codegen.cpp: reassert that there are no generated
errors in codegen;
Tracking Issue #1296 ;
Thanks @andrewrk ;
---
src/codegen.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 8a18a3f8dd..54effb9480 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -6014,7 +6014,7 @@ static void do_code_gen(CodeGen *g) {
}
- //assert(!g->errors.length);
+ assert(!g->errors.length);
if (buf_len(&g->global_asm) != 0) {
LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm));
From c1a3b0cb0af3c0639ce09b2a17a3cc90977346fe Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 15:23:09 +0900
Subject: [PATCH 10/39] src/ir.cpp: add/throw error for @handle() in a non
async context;
Tracking Issue #1296 ;
Thanks @andrewrk ;
---
src/ir.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index 50c8c70290..1e9d1bdb7e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -3858,6 +3858,8 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
return irb->codegen->invalid_instruction;
}
+ bool is_async = exec_is_async(irb->exec);
+
switch (builtin_fn->id) {
case BuiltinFnIdInvalid:
zig_unreachable();
@@ -4491,6 +4493,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
case BuiltinFnIdFrameAddress:
return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
case BuiltinFnIdHandle:
+ if (!is_async) {
+ add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
+ return irb->codegen->invalid_instruction;
+ }
return ir_lval_wrap(irb, scope, ir_build_handle(irb, scope, node), lval);
case BuiltinFnIdAlignOf:
{
From 1f0040dd92f64cebf77a5ce34bd72984d92b3f2f Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 15:37:23 +0900
Subject: [PATCH 11/39] test/cases/coroutines.zig: remove dummy assert used for
testing;
---
test/cases/coroutines.zig | 3 ---
1 file changed, 3 deletions(-)
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index deb4aa1b24..53c5c3f906 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -57,9 +57,6 @@ test "coroutine suspend with block" {
resume a_promise;
std.debug.assert(result);
cancel p;
-
- assert( @handle() );
-
}
var a_promise: promise = undefined;
From fcf53b31fc2899cba682c4c9a8cade40c6e0ab9e Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 15:38:22 +0900
Subject: [PATCH 12/39] src/ir.cpp: return promise->T instead of promise;
Tracking Issue #1296 ;
Thanks @andrewrk ;
---
src/ir.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 1e9d1bdb7e..9712cb0bc2 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -19033,8 +19033,9 @@ static TypeTableEntry *ir_analyze_instruction_frame_address(IrAnalyze *ira, IrIn
static TypeTableEntry *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructionHandle *instruction) {
ir_build_handle_from(&ira->new_irb, &instruction->base);
- TypeTableEntry *promise_type = get_promise_type(ira->codegen, nullptr);
- return promise_type;
+ FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ assert(fn_entry != nullptr);
+ return get_promise_type(ira->codegen, fn_entry->type_entry->data.fn.fn_type_id.return_type);
}
static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) {
From a8ea2360958354ba8310c7cea388351299e72e44 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 17:35:50 +0900
Subject: [PATCH 13/39] src/ir.cpp: don't allow `@handle()` outside of a
function;
Tracking Issue #1296 ;
---
src/ir.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/ir.cpp b/src/ir.cpp
index 9712cb0bc2..966d8e9f33 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -4493,6 +4493,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
case BuiltinFnIdFrameAddress:
return ir_lval_wrap(irb, scope, ir_build_frame_address(irb, scope, node), lval);
case BuiltinFnIdHandle:
+ if (!irb->exec->fn_entry) {
+ add_node_error(irb->codegen, node, buf_sprintf("@handle() called outside of function definition"));
+ return irb->codegen->invalid_instruction;
+ }
if (!is_async) {
add_node_error(irb->codegen, node, buf_sprintf("@handle() in non-async function"));
return irb->codegen->invalid_instruction;
From 104bdb03d6b5906716efeb84045079a424bf650a Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 23:29:40 +0900
Subject: [PATCH 14/39] src/codegen.cpp: return promise instead of null
promise;
Tracking Issue #1296 ;
---
src/codegen.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 54effb9480..bd708e3824 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4149,7 +4149,8 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
IrInstructionHandle *instruction)
{
- return LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+ LLVMValueRef ptr = ir_llvm_value(g, executable->fn_entry->ir_executable.coro_handle->other);
+ return LLVMBuildBitCast(g->builder, ptr, g->builtin_types.entry_promise->type_ref, "");
}
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
From c546f750f14e63b80c01d707c5559524313edfe4 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 23:51:48 +0900
Subject: [PATCH 15/39] test/compile_errors.zig: @handle() called outside of
function definition;
Tracking Issue #1296 ;
---
test/compile_errors.zig | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 2c4c9208eb..c34b325a78 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -4738,4 +4738,20 @@ 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",
+ );
}
From 13ec5db2348a0f6a4464aa8a513dbf11b72dc3ae Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sat, 28 Jul 2018 23:52:12 +0900
Subject: [PATCH 16/39] test/compile_errors.zig: @handle() in non-async
function
Tracking Issue #1296 ;
---
test/compile_errors.zig | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index c34b325a78..241f3a47a8 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -4754,4 +4754,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
,
".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",
+ );
}
From 92cb330e160388bca7ddd7ceecbd7157ce92247b Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 12:27:50 +0900
Subject: [PATCH 17/39] src/codegen.cpp: @handle(): replace hacky ref chain
with llvm intrinsic;
Tracking Issue #1296 ;
---
src/all_types.hpp | 1 +
src/codegen.cpp | 17 +++++++++++++++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index f03a250aea..8d55a75f9f 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1717,6 +1717,7 @@ struct CodeGen {
LLVMValueRef coro_save_fn_val;
LLVMValueRef coro_promise_fn_val;
LLVMValueRef coro_alloc_helper_fn_val;
+ LLVMValueRef coro_frame_fn_val;
LLVMValueRef merge_err_ret_traces_fn_val;
LLVMValueRef add_error_return_trace_addr_fn_val;
LLVMValueRef stacksave_fn_val;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index bd708e3824..539356ef2f 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -4146,11 +4146,24 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable
return LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, "");
}
+static LLVMValueRef get_handle_fn_val(CodeGen *g) {
+ if (g->coro_frame_fn_val)
+ return g->coro_frame_fn_val;
+
+ LLVMTypeRef fn_type = LLVMFunctionType( LLVMPointerType(LLVMInt8Type(), 0)
+ , nullptr, 0, false);
+ Buf *name = buf_sprintf("llvm.coro.frame");
+ g->coro_frame_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type);
+ assert(LLVMGetIntrinsicID(g->coro_frame_fn_val));
+
+ return g->coro_frame_fn_val;
+}
+
static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable,
IrInstructionHandle *instruction)
{
- LLVMValueRef ptr = ir_llvm_value(g, executable->fn_entry->ir_executable.coro_handle->other);
- return LLVMBuildBitCast(g->builder, ptr, g->builtin_types.entry_promise->type_ref, "");
+ LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_promise->type_ref);
+ return LLVMBuildCall(g->builder, get_handle_fn_val(g), &zero, 0, "");
}
static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp *instruction) {
From ca1b3563372dbf4442b5c3ff0fecaa174aea06b7 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:09:00 +0900
Subject: [PATCH 18/39] src/all_types.hpp: remove promise_symbol from suspend;
Tracking Issue #1296 ;
---
src/all_types.hpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 8d55a75f9f..b1e8a3746d 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -899,7 +899,6 @@ struct AstNodeAwaitExpr {
struct AstNodeSuspend {
AstNode *block;
- AstNode *promise_symbol;
};
struct AstNodePromiseType {
From 5e5685c1174350b00ebf3e9ac49e244fa38fc0ac Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:09:39 +0900
Subject: [PATCH 19/39] src/ast_render.cpp: remove promise_symbol from suspend;
Tracking Issue #1296 ;
---
src/ast_render.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 2ace00885d..984b4230b1 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -1112,9 +1112,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
{
fprintf(ar->f, "suspend");
if (node->data.suspend.block != nullptr) {
- fprintf(ar->f, " |");
- render_node_grouped(ar, node->data.suspend.promise_symbol);
- fprintf(ar->f, "| ");
render_node_grouped(ar, node->data.suspend.block);
}
break;
From b3cd65d56e2efc3e0f67461dbad75747b2db3aa7 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:10:48 +0900
Subject: [PATCH 20/39] src/ir.cpp: remove promise_symbol from suspend;
Tracking Issue #1296 ;
---
src/ir.cpp | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
index 966d8e9f33..7d2881744d 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -7096,19 +7096,8 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
if (node->data.suspend.block == nullptr) {
suspend_code = ir_build_coro_suspend(irb, parent_scope, node, nullptr, const_bool_false);
} else {
- assert(node->data.suspend.promise_symbol != nullptr);
- assert(node->data.suspend.promise_symbol->type == NodeTypeSymbol);
- Buf *promise_symbol_name = node->data.suspend.promise_symbol->data.symbol_expr.symbol;
Scope *child_scope;
- if (!buf_eql_str(promise_symbol_name, "_")) {
- VariableTableEntry *promise_var = ir_create_var(irb, node, parent_scope, promise_symbol_name,
- true, true, false, const_bool_false);
- ir_build_var_decl(irb, parent_scope, node, promise_var, nullptr, nullptr, irb->exec->coro_handle);
- child_scope = promise_var->child_scope;
- } else {
- child_scope = parent_scope;
- }
- ScopeSuspend *suspend_scope = create_suspend_scope(node, child_scope);
+ ScopeSuspend *suspend_scope = create_suspend_scope(node, parent_scope);
suspend_scope->resume_block = resume_block;
child_scope = &suspend_scope->base;
IrInstruction *save_token = ir_build_coro_save(irb, child_scope, node, irb->exec->coro_handle);
From d3f628907a6b9e5b863c9d5235e6dadf57f42ca2 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:11:43 +0900
Subject: [PATCH 21/39] src/parser.cpp: remove promise_symbol from suspend;
Tracking Issue #1296 ;
---
src/parser.cpp | 31 ++++++++++++++++---------------
1 file changed, 16 insertions(+), 15 deletions(-)
diff --git a/src/parser.cpp b/src/parser.cpp
index a93d8de830..e2a818a56c 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -648,35 +648,37 @@ static AstNode *ast_parse_asm_expr(ParseContext *pc, size_t *token_index, bool m
}
/*
-SuspendExpression(body) = "suspend" option(("|" Symbol "|" body))
+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 (suspend_token->id == TokenIdKeywordSuspend) {
*token_index += 1;
+ suspend_token = token;
+ token = &pc->tokens->at(*token_index);
} else if (mandatory) {
- ast_expect_token(pc, suspend_token, TokenIdKeywordSuspend);
+ ast_expect_token(pc, token, TokenIdKeywordSuspend);
zig_unreachable();
} else {
return nullptr;
}
- Token *bar_token = &pc->tokens->at(*token_index);
- if (bar_token->id == TokenIdBinOr) {
- *token_index += 1;
- } else if (mandatory) {
- ast_expect_token(pc, suspend_token, TokenIdBinOr);
- zig_unreachable();
- } else {
- *token_index = orig_token_index;
- 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;
+ }
}
+ //Expect that we have a block;
AstNode *node = ast_create_node(pc, NodeTypeSuspend, suspend_token);
- node->data.suspend.promise_symbol = ast_parse_symbol(pc, token_index);
- ast_eat_token(pc, token_index, TokenIdBinOr);
node->data.suspend.block = ast_parse_block(pc, token_index, true);
return node;
@@ -3134,7 +3136,6 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
visit_field(&node->data.await_expr.expr, visit, context);
break;
case NodeTypeSuspend:
- visit_field(&node->data.suspend.promise_symbol, visit, context);
visit_field(&node->data.suspend.block, visit, context);
break;
}
From 29057e5511ed007ee8db8306e89b674384c35964 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:12:33 +0900
Subject: [PATCH 22/39] std/event/channel.zig: remove promise_symbol from
suspend and use @handle();
Tracking Issue #1296 ;
---
std/event/channel.zig | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/std/event/channel.zig b/std/event/channel.zig
index 03a036042b..71e97f6e78 100644
--- a/std/event/channel.zig
+++ b/std/event/channel.zig
@@ -71,10 +71,10 @@ pub fn Channel(comptime T: type) type {
/// puts a data item in the channel. The promise completes when the value has been added to the
/// buffer, or in the case of a zero size buffer, when the item has been retrieved by a getter.
pub async fn put(self: *SelfChannel, data: T) void {
- suspend |handle| {
+ suspend {
var my_tick_node = Loop.NextTickNode{
.next = undefined,
- .data = handle,
+ .data = @handle(),
};
var queue_node = std.atomic.Queue(PutNode).Node{
.data = PutNode{
@@ -96,10 +96,10 @@ pub fn Channel(comptime T: type) type {
// TODO integrate this function with named return values
// so we can get rid of this extra result copy
var result: T = undefined;
- suspend |handle| {
+ suspend {
var my_tick_node = Loop.NextTickNode{
.next = undefined,
- .data = handle,
+ .data = @handle(),
};
var queue_node = std.atomic.Queue(GetNode).Node{
.data = GetNode{
From 244a7fdafb97b215e0e9e3e8aaa23777eccebd14 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:12:52 +0900
Subject: [PATCH 23/39] std/event/future.zig: remove promise_symbol from
suspend and use @handle();
Tracking Issue #1296 ;
---
std/event/future.zig | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/std/event/future.zig b/std/event/future.zig
index f5d14d1ca6..f9b9db86a7 100644
--- a/std/event/future.zig
+++ b/std/event/future.zig
@@ -100,8 +100,9 @@ test "std.event.Future" {
}
async fn testFuture(loop: *Loop) void {
- suspend |p| {
- resume p;
+ suspend {
+ var h: promise = @handle();
+ resume h;
}
var future = Future(i32).init(loop);
@@ -115,15 +116,17 @@ async fn testFuture(loop: *Loop) void {
}
async fn waitOnFuture(future: *Future(i32)) i32 {
- suspend |p| {
- resume p;
+ suspend {
+ var h: promise = @handle();
+ resume h;
}
return (await (async future.get() catch @panic("memory"))).*;
}
async fn resolveFuture(future: *Future(i32)) void {
- suspend |p| {
- resume p;
+ suspend {
+ var h: promise = @handle();
+ resume h;
}
future.data = 6;
future.resolve();
From b4ff464d39038fe840ed6fce3f73cd075fde25f2 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:13:16 +0900
Subject: [PATCH 24/39] std/event/group.zig: remove promise_symbol from suspend
and use @handle();
Tracking Issue #1296 ;
---
std/event/group.zig | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/std/event/group.zig b/std/event/group.zig
index 26c098399e..493913010f 100644
--- a/std/event/group.zig
+++ b/std/event/group.zig
@@ -54,10 +54,11 @@ pub fn Group(comptime ReturnType: type) type {
const S = struct {
async fn asyncFunc(node: **Stack.Node, args2: ...) ReturnType {
// TODO this is a hack to make the memory following be inside the coro frame
- suspend |p| {
+ suspend {
var my_node: Stack.Node = undefined;
node.* = &my_node;
- resume p;
+ var h: promise = @handle();
+ resume h;
}
// TODO this allocation elision should be guaranteed because we await it in
From efec3a0e342be01f7cf74cf7906dd50b98e5aa97 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:13:42 +0900
Subject: [PATCH 25/39] std/event/lock.zig: remove promise_symbol from suspend
and use @handle();
Tracking Issue #1296 ;
---
std/event/lock.zig | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/std/event/lock.zig b/std/event/lock.zig
index 0bd7183db2..2769a2153c 100644
--- a/std/event/lock.zig
+++ b/std/event/lock.zig
@@ -90,10 +90,10 @@ pub const Lock = struct {
}
pub async fn acquire(self: *Lock) Held {
- suspend |handle| {
+ suspend {
// TODO explicitly put this memory in the coroutine frame #1194
var my_tick_node = Loop.NextTickNode{
- .data = handle,
+ .data = @handle(),
.next = undefined,
};
@@ -141,8 +141,9 @@ test "std.event.Lock" {
async fn testLock(loop: *Loop, lock: *Lock) void {
// TODO explicitly put next tick node memory in the coroutine frame #1194
- suspend |p| {
- resume p;
+ suspend {
+ var h: promise = @handle();
+ resume h;
}
const handle1 = async lockRunner(lock) catch @panic("out of memory");
var tick_node1 = Loop.NextTickNode{
From a3705b425134d8e9c22ce238e7de9568d3394a44 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:14:02 +0900
Subject: [PATCH 26/39] std/event/loop.zig: remove promise_symbol from suspend
and use @handle();
Tracking Issue #1296 ;
---
std/event/loop.zig | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/std/event/loop.zig b/std/event/loop.zig
index 4e219653be..8b1b2e53db 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -331,11 +331,11 @@ pub const Loop = struct {
pub async fn waitFd(self: *Loop, fd: i32) !void {
defer self.removeFd(fd);
- suspend |p| {
+ suspend {
// TODO explicitly put this memory in the coroutine frame #1194
var resume_node = ResumeNode{
.id = ResumeNode.Id.Basic,
- .handle = p,
+ .handle = @handle(),
};
try self.addFd(fd, &resume_node);
}
@@ -417,11 +417,11 @@ pub const Loop = struct {
pub fn call(self: *Loop, comptime func: var, args: ...) !(promise->@typeOf(func).ReturnType) {
const S = struct {
async fn asyncFunc(loop: *Loop, handle: *promise->@typeOf(func).ReturnType, args2: ...) @typeOf(func).ReturnType {
- suspend |p| {
- handle.* = p;
+ suspend {
+ handle.* = @handle();
var my_tick_node = Loop.NextTickNode{
.next = undefined,
- .data = p,
+ .data = @handle(),
};
loop.onNextTick(&my_tick_node);
}
@@ -439,10 +439,10 @@ pub const Loop = struct {
/// CPU bound tasks would be waiting in the event loop but never get started because no async I/O
/// is performed.
pub async fn yield(self: *Loop) void {
- suspend |p| {
+ suspend {
var my_tick_node = Loop.NextTickNode{
.next = undefined,
- .data = p,
+ .data = @handle(),
};
self.onNextTick(&my_tick_node);
}
From 9fe140abad11a15a8bb81b3599600ca1ec6f00d0 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:14:35 +0900
Subject: [PATCH 27/39] std/event/tcp.zig: remove promise_symbol from suspend
and use @handle();
Tracking Issue #1296 ;
---
std/event/tcp.zig | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/std/event/tcp.zig b/std/event/tcp.zig
index 416a8c07dc..9a3c6f95ca 100644
--- a/std/event/tcp.zig
+++ b/std/event/tcp.zig
@@ -88,8 +88,8 @@ pub const Server = struct {
},
error.ProcessFdQuotaExceeded => {
errdefer std.os.emfile_promise_queue.remove(&self.waiting_for_emfile_node);
- suspend |p| {
- self.waiting_for_emfile_node = PromiseNode.init(p);
+ suspend {
+ self.waiting_for_emfile_node = PromiseNode.init( @handle() );
std.os.emfile_promise_queue.append(&self.waiting_for_emfile_node);
}
continue;
@@ -141,8 +141,9 @@ test "listen on a port, send bytes, receive bytes" {
(await next_handler) catch |err| {
std.debug.panic("unable to handle connection: {}\n", err);
};
- suspend |p| {
- cancel p;
+ suspend {
+ var h: promise = @handle();
+ cancel h;
}
}
async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: *const std.os.File) !void {
From bc032a89cc13e483a55c58bcba4593229dd7f3ed Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:16:36 +0900
Subject: [PATCH 28/39] std/zig/parser_test.zig: update test to reflect that
the promise symbol is no in scope with suspend;
Tracking Issue #1296 ;
---
std/zig/parser_test.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 21259bec3c..32cdc8121f 100644
--- a/std/zig/parser_test.zig
+++ b/std/zig/parser_test.zig
@@ -1784,7 +1784,7 @@ test "zig fmt: coroutines" {
\\ x += 1;
\\ suspend;
\\ x += 1;
- \\ suspend |p| {}
+ \\ suspend;
\\ const p: promise->void = async simpleAsyncFn() catch unreachable;
\\ await p;
\\}
From 79792a32e19b5ef7a918655f09ac32dd94c8f19e Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:17:13 +0900
Subject: [PATCH 29/39] test/cases/coroutine_await_struct.zig: update test to
reflect that the promise symbol is no in scope with suspend;
Tracking Issue #1296 ;
---
test/cases/coroutine_await_struct.zig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/cases/coroutine_await_struct.zig b/test/cases/coroutine_await_struct.zig
index 56c526092d..79168715d8 100644
--- a/test/cases/coroutine_await_struct.zig
+++ b/test/cases/coroutine_await_struct.zig
@@ -30,9 +30,9 @@ async fn await_amain() void {
}
async fn await_another() Foo {
await_seq('c');
- suspend |p| {
+ suspend {
await_seq('d');
- await_a_promise = p;
+ await_a_promise = @handle();
}
await_seq('g');
return Foo{ .x = 1234 };
From 3241ada4682b6953431876edfb8fc7af0f346a34 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:17:48 +0900
Subject: [PATCH 30/39] test/cases/coroutines.zig: update test to reflect that
the promise symbol is no in scope with suspend;
Tracking Issue #1296 ;
---
test/cases/coroutines.zig | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 53c5c3f906..c2aeb5de83 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -62,9 +62,9 @@ test "coroutine suspend with block" {
var a_promise: promise = undefined;
var result = false;
async fn testSuspendBlock() void {
- suspend |p| {
- comptime assert(@typeOf(p) == promise->void);
- a_promise = p;
+ suspend {
+ comptime assert(@typeOf(@handle()) == promise->void);
+ a_promise = @handle();
}
//Test to make sure that @handle() works as advertised (issue #1296)
@@ -98,9 +98,9 @@ async fn await_amain() void {
}
async fn await_another() i32 {
await_seq('c');
- suspend |p| {
+ suspend {
await_seq('d');
- await_a_promise = p;
+ await_a_promise = @handle();
}
await_seq('g');
return 1234;
From 9b3cebcdb9bedfa2ef49ddfb0dffea0899ab558d Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:18:31 +0900
Subject: [PATCH 31/39] test/cases/coroutines.zig: test for immediate resume
inside of suspend with @handle();
Tracking Issue #1296 ;
---
test/cases/coroutines.zig | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index c2aeb5de83..4dc20b9cfc 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -256,3 +256,19 @@ 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 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
From 51955a5ca2b6f3f005e28cd3758dc481c2eea0c3 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:18:54 +0900
Subject: [PATCH 32/39] test/compile_errors.zig: update test to reflect that
the promise symbol is no in scope with suspend;
Tracking Issue #1296 ;
---
test/compile_errors.zig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index 241f3a47a8..f4b289f70d 100644
--- a/test/compile_errors.zig
+++ b/test/compile_errors.zig
@@ -367,8 +367,8 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\}
\\
\\async fn foo() void {
- \\ suspend |p| {
- \\ suspend |p1| {
+ \\ suspend {
+ \\ suspend {
\\ }
\\ }
\\}
From ff4a03f35157c3c82d581a599bf98db86504ecc1 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Sun, 29 Jul 2018 17:19:36 +0900
Subject: [PATCH 33/39] doc/langref.html.in: update docs to reflect that the
promise symbol is no in scope with suspend;
Tracking Issue #1296 ;
---
doc/langref.html.in | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 7fde550338..58b63f7f40 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4690,9 +4690,9 @@ test "coroutine suspend with block" {
var a_promise: promise = undefined;
var result = false;
async fn testSuspendBlock() void {
- suspend |p| {
- comptime assert(@typeOf(p) == promise->void);
- a_promise = p;
+ suspend {
+ comptime assert(@typeOf(@handle()) == promise->void);
+ a_promise = @handle();
}
result = true;
}
@@ -4791,9 +4791,9 @@ async fn amain() void {
}
async fn another() i32 {
seq('c');
- suspend |p| {
+ suspend {
seq('d');
- a_promise = p;
+ a_promise = @handle();
}
seq('g');
return 1234;
@@ -7388,7 +7388,7 @@ Defer(body) = ("defer" | "deferror") body
IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body))
-SuspendExpression(body) = "suspend" option(("|" Symbol "|" body))
+SuspendExpression(body) = "suspend" option( body )
IfErrorExpression(body) = "if" "(" Expression ")" option("|" option("*") Symbol "|") body "else" "|" Symbol "|" BlockExpression(body)
From 5de92425d57338ba6c94a90360f96eb2fa8efdda Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:11:37 +0900
Subject: [PATCH 34/39] src/parser.cpp: fix typo from rebase;
---
src/parser.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/parser.cpp b/src/parser.cpp
index e2a818a56c..84ccdbeea8 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -655,7 +655,7 @@ static AstNode *ast_parse_suspend_block(ParseContext *pc, size_t *token_index, b
Token *token = &pc->tokens->at(*token_index);
Token *suspend_token = nullptr;
- if (suspend_token->id == TokenIdKeywordSuspend) {
+ if (token->id == TokenIdKeywordSuspend) {
*token_index += 1;
suspend_token = token;
token = &pc->tokens->at(*token_index);
From 915e321a2334b32ae398ec669d059f43fc2a8774 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:45:35 +0900
Subject: [PATCH 35/39] doc/langref.html.in: update suspend example with
@handle();
Tracking Issue #1296 ;
---
doc/langref.html.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 58b63f7f40..92fae2347d 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -4733,8 +4733,8 @@ test "resume from suspend" {
std.debug.assert(my_result == 2);
}
async fn testResumeFromSuspend(my_result: *i32) void {
- suspend |p| {
- resume p;
+ suspend {
+ resume @handle();
}
my_result.* += 1;
suspend;
From 9bed23f8b77531b1699ff79bbdd8bc9281ddfe5d Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:46:41 +0900
Subject: [PATCH 36/39] test/cases/coroutines.zig: update suspend to use
@handle();
Tracking Issue #1296 ;
---
test/cases/coroutines.zig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index 4dc20b9cfc..a955eeac37 100644
--- a/test/cases/coroutines.zig
+++ b/test/cases/coroutines.zig
@@ -249,8 +249,8 @@ test "break from suspend" {
std.debug.assert(my_result == 2);
}
async fn testBreakFromSuspend(my_result: *i32) void {
- suspend |p| {
- resume p;
+ suspend {
+ resume @handle();
}
my_result.* += 1;
suspend;
From 9b890d70675b105ba2810e6b08010098e198043c Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:47:03 +0900
Subject: [PATCH 37/39] test/cases/cancel.zig: update suspend to use @handle();
Tracking Issue #1296 ;
---
test/cases/cancel.zig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/cases/cancel.zig b/test/cases/cancel.zig
index edf11d687d..c0f74fd34f 100644
--- a/test/cases/cancel.zig
+++ b/test/cases/cancel.zig
@@ -85,8 +85,8 @@ async fn b4() void {
defer {
defer_b4 = true;
}
- suspend |p| {
- b4_handle = p;
+ suspend {
+ b4_handle = @handle();
}
suspend;
}
From ac0a87d58d72a8c1fbb9b0af2d3818075729d85a Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:47:39 +0900
Subject: [PATCH 38/39] doc/langref.html.in: add builtin @handle() to docs;
Tracking Issue #1296 ;
---
doc/langref.html.in | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/doc/langref.html.in b/doc/langref.html.in
index 92fae2347d..54677bc5b5 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -5383,6 +5383,16 @@ test "main" {
This function is only valid within function scope.
{#header_close#}
+ {#header_open|@handle#}
+ @handle()
+
+ This function returns a promise->T type, where T
+ is the return type of the async function in scope.
+
+
+ This function is only valid within an async function scope.
+
+ {#header_close#}
{#header_open|@import#}
@import(comptime path: []u8) (namespace)
From 96a94e7da933dafec25356c435f5725c3cb0ce04 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Thu, 2 Aug 2018 17:52:40 +0900
Subject: [PATCH 39/39] std/event: directly return @handle();
Tracking Issue #1296 ;
---
std/event/future.zig | 9 +++------
std/event/group.zig | 3 +--
std/event/lock.zig | 3 +--
std/event/tcp.zig | 3 +--
4 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/std/event/future.zig b/std/event/future.zig
index f9b9db86a7..8abdce7d02 100644
--- a/std/event/future.zig
+++ b/std/event/future.zig
@@ -101,8 +101,7 @@ test "std.event.Future" {
async fn testFuture(loop: *Loop) void {
suspend {
- var h: promise = @handle();
- resume h;
+ resume @handle();
}
var future = Future(i32).init(loop);
@@ -117,16 +116,14 @@ async fn testFuture(loop: *Loop) void {
async fn waitOnFuture(future: *Future(i32)) i32 {
suspend {
- var h: promise = @handle();
- resume h;
+ resume @handle();
}
return (await (async future.get() catch @panic("memory"))).*;
}
async fn resolveFuture(future: *Future(i32)) void {
suspend {
- var h: promise = @handle();
- resume h;
+ resume @handle();
}
future.data = 6;
future.resolve();
diff --git a/std/event/group.zig b/std/event/group.zig
index 493913010f..6c7fc63699 100644
--- a/std/event/group.zig
+++ b/std/event/group.zig
@@ -57,8 +57,7 @@ pub fn Group(comptime ReturnType: type) type {
suspend {
var my_node: Stack.Node = undefined;
node.* = &my_node;
- var h: promise = @handle();
- resume h;
+ resume @handle();
}
// TODO this allocation elision should be guaranteed because we await it in
diff --git a/std/event/lock.zig b/std/event/lock.zig
index 2769a2153c..c4cb1a3f0e 100644
--- a/std/event/lock.zig
+++ b/std/event/lock.zig
@@ -142,8 +142,7 @@ test "std.event.Lock" {
async fn testLock(loop: *Loop, lock: *Lock) void {
// TODO explicitly put next tick node memory in the coroutine frame #1194
suspend {
- var h: promise = @handle();
- resume h;
+ resume @handle();
}
const handle1 = async lockRunner(lock) catch @panic("out of memory");
var tick_node1 = Loop.NextTickNode{
diff --git a/std/event/tcp.zig b/std/event/tcp.zig
index 9a3c6f95ca..ea803a9322 100644
--- a/std/event/tcp.zig
+++ b/std/event/tcp.zig
@@ -142,8 +142,7 @@ test "listen on a port, send bytes, receive bytes" {
std.debug.panic("unable to handle connection: {}\n", err);
};
suspend {
- var h: promise = @handle();
- cancel h;
+ cancel @handle();
}
}
async fn errorableHandler(self: *Self, _addr: *const std.net.Address, _socket: *const std.os.File) !void {