Date: Thu, 2 Aug 2018 17:47:39 +0900
Subject: [PATCH 42/50] 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 92fae2347..54677bc5b 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 43/50] 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 f9b9db86a..8abdce7d0 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 493913010..6c7fc6369 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 2769a2153..c4cb1a3f0 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 9a3c6f95c..ea803a932 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 {
From 432b7685bfa840a459b492a37894f7ffed870c7e Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 3 Aug 2018 01:59:59 +0900
Subject: [PATCH 44/50] std/os/index.zig: use "hw.logicalcpu" instead of
"hw.ncpu" in macOS; (#1317)
Tracking Issue #1252 ;
hw.ncpu was deprecated in macOS. Among 4 new options available (hw.{physicalcpu, physicalcpu_max, logicalcpu, logicalcpu_max}), hw.logicalcpu was chosen because it actually reflects the number of logical cores the OS sees.
---
std/os/index.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index 77fd2a78a..0a6f598a2 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -2790,7 +2790,7 @@ pub fn cpuCount(fallback_allocator: *mem.Allocator) CpuCountError!usize {
builtin.Os.macosx => {
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
- const rc = posix.sysctlbyname(c"hw.ncpu", @ptrCast(*c_void, &count), &count_len, null, 0);
+ const rc = posix.sysctlbyname(c"hw.logicalcpu", @ptrCast(*c_void, &count), &count_len, null, 0);
const err = posix.getErrno(rc);
switch (err) {
0 => return @intCast(usize, count),
From 22fd359e2c601c9d0a009705bed60c88821f2b0f Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 3 Aug 2018 02:14:06 +0900
Subject: [PATCH 45/50] std/os/windows/advapi32.zig: add SystemFunction036;
Tracking Issue #1318 ;
---
std/os/windows/advapi32.zig | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/std/os/windows/advapi32.zig b/std/os/windows/advapi32.zig
index dcb5a636e..64a820a3b 100644
--- a/std/os/windows/advapi32.zig
+++ b/std/os/windows/advapi32.zig
@@ -28,3 +28,8 @@ pub extern "advapi32" stdcallcc fn RegOpenKeyExW(hKey: HKEY, lpSubKey: LPCWSTR,
pub extern "advapi32" stdcallcc fn RegQueryValueExW(hKey: HKEY, lpValueName: LPCWSTR, lpReserved: LPDWORD,
lpType: LPDWORD, lpData: LPBYTE, lpcbData: LPDWORD,) LSTATUS;
+
+// RtlGenRandom is known as SystemFunction036 under advapi32
+// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
+pub extern "advapi32" stdcallcc fn SystemFunction036(output: PVOID, length: ULONG_PTR) BOOL;
+pub const RtlGenRandom = SystemFunction036;
From c44653f40f37c93fc68a2e455d693bb11f1c11d3 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 3 Aug 2018 02:14:52 +0900
Subject: [PATCH 46/50] std/os/index.zig: swap CryptGetRandom() with
RtlGenRandom();
Tracking Issue #1318 ;
---
std/os/index.zig | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index 77fd2a78a..7042247a2 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -130,16 +130,10 @@ pub fn getRandomBytes(buf: []u8) !void {
try posixRead(fd, buf);
},
Os.windows => {
- var hCryptProv: windows.HCRYPTPROV = undefined;
- if (windows.CryptAcquireContextA(&hCryptProv, null, null, windows.PROV_RSA_FULL, 0) == 0) {
- const err = windows.GetLastError();
- return switch (err) {
- else => unexpectedErrorWindows(err),
- };
- }
- defer _ = windows.CryptReleaseContext(hCryptProv, 0);
-
- if (windows.CryptGenRandom(hCryptProv, @intCast(windows.DWORD, buf.len), buf.ptr) == 0) {
+ // Call RtlGenRandom() instead of CryptGetRandom() on Windows
+ // https://github.com/rust-lang-nursery/rand/issues/111
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=504270
+ if (!windows.RtlGenRandom(buf.ptr, buf.len)) {
const err = windows.GetLastError();
return switch (err) {
else => unexpectedErrorWindows(err),
From dde7eb45c51dd96242a6b028eb1912ee6ffa2c55 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 3 Aug 2018 02:16:19 +0900
Subject: [PATCH 47/50] std/os/index.zig: call getRandomBytes() twice and
compare;
Tracking Issue #1318 ;
---
std/os/index.zig | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index 7042247a2..87edce3da 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -153,8 +153,14 @@ pub fn getRandomBytes(buf: []u8) !void {
}
test "os.getRandomBytes" {
- var buf: [50]u8 = undefined;
- try getRandomBytes(buf[0..]);
+ var buf_a: [50]u8 = undefined;
+ var buf_b: [50]u8 = undefined;
+ // Call Twice
+ try getRandomBytes(buf_a[0..]);
+ try getRandomBytes(buf_b[0..]);
+
+ // Check if random (not 100% conclusive)
+ assert( !mem.eql(u8, buf_a, buf_b) );
}
/// Raises a signal in the current kernel thread, ending its execution.
From 782043e2e66ab5833cb20dc6e787b87eb84165f8 Mon Sep 17 00:00:00 2001
From: kristopher tate
Date: Fri, 3 Aug 2018 02:16:49 +0900
Subject: [PATCH 48/50] std/os/windows/util.zig: SKIP instead of PASS on
non-windows systems;
Tracking Issue #1318 ;
---
std/os/windows/util.zig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig
index dda9ce7a8..c9d2c3c3e 100644
--- a/std/os/windows/util.zig
+++ b/std/os/windows/util.zig
@@ -166,7 +166,7 @@ pub fn windowsUnloadDll(hModule: windows.HMODULE) void {
}
test "InvalidDll" {
- if (builtin.os != builtin.Os.windows) return;
+ if (builtin.os != builtin.Os.windows) return error.SkipZigTest;
const DllName = "asdf.dll";
const allocator = std.debug.global_allocator;
From 729f2aceb045e54b2b74a33fa5f64cb9802988c6 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 2 Aug 2018 13:34:31 -0400
Subject: [PATCH 49/50] fix API of RtlGenRandom
---
std/os/index.zig | 2 +-
std/os/windows/advapi32.zig | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/std/os/index.zig b/std/os/index.zig
index b5e0129da..425a900a7 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -133,7 +133,7 @@ pub fn getRandomBytes(buf: []u8) !void {
// Call RtlGenRandom() instead of CryptGetRandom() on Windows
// https://github.com/rust-lang-nursery/rand/issues/111
// https://bugzilla.mozilla.org/show_bug.cgi?id=504270
- if (!windows.RtlGenRandom(buf.ptr, buf.len)) {
+ if (windows.RtlGenRandom(buf.ptr, buf.len) == 0) {
const err = windows.GetLastError();
return switch (err) {
else => unexpectedErrorWindows(err),
diff --git a/std/os/windows/advapi32.zig b/std/os/windows/advapi32.zig
index 64a820a3b..2f3195475 100644
--- a/std/os/windows/advapi32.zig
+++ b/std/os/windows/advapi32.zig
@@ -31,5 +31,5 @@ pub extern "advapi32" stdcallcc fn RegQueryValueExW(hKey: HKEY, lpValueName: LPC
// RtlGenRandom is known as SystemFunction036 under advapi32
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx */
-pub extern "advapi32" stdcallcc fn SystemFunction036(output: PVOID, length: ULONG_PTR) BOOL;
+pub extern "advapi32" stdcallcc fn SystemFunction036(output: [*]u8, length: usize) BOOL;
pub const RtlGenRandom = SystemFunction036;
From 895f262a55b9951647efef4528c17cf64d6b7c07 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Thu, 2 Aug 2018 14:15:31 -0400
Subject: [PATCH 50/50] pull request fixups
* clean up parser code
* fix stage2 parse and render code
* remove redundant test
* make stage1 compile tests leaner
---
src/parser.cpp | 36 +++++++++++----------------
std/zig/ast.zig | 12 ---------
std/zig/parse.zig | 33 +++++++++++--------------
std/zig/parser_test.zig | 6 ++---
std/zig/render.zig | 16 +-----------
test/cases/coroutines.zig | 16 ------------
test/compile_errors.zig | 51 ++++++++++++++++-----------------------
7 files changed, 53 insertions(+), 117 deletions(-)
diff --git a/src/parser.cpp b/src/parser.cpp
index 84ccdbeea..453ab7ce2 100644
--- a/src/parser.cpp
+++ b/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;
}
/*
diff --git a/std/zig/ast.zig b/std/zig/ast.zig
index 004f9278b..95e899fb9 100644
--- a/std/zig/ast.zig
+++ b/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;
}
};
diff --git a/std/zig/parse.zig b/std/zig/parse.zig
index 73d51e787..fb49d2a2b 100644
--- a/std/zig/parse.zig
+++ b/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 => {
diff --git a/std/zig/parser_test.zig b/std/zig/parser_test.zig
index 32cdc8121..582bffdf3 100644
--- a/std/zig/parser_test.zig
+++ b/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();
\\ }
\\}
\\
diff --git a/std/zig/render.zig b/std/zig/render.zig
index bc45768fa..868902a0d 100644
--- a/std/zig/render.zig
+++ b/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 {
diff --git a/test/cases/coroutines.zig b/test/cases/coroutines.zig
index a955eeac3..bd6b6abf6 100644
--- a/test/cases/coroutines.zig
+++ b/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 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
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
index f4b289f70..948d212e5 100644
--- a/test/compile_errors.zig
+++ b/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",
- );
}