From 92a423739d91bd0677940fc1a86b593649cafaa6 Mon Sep 17 00:00:00 2001 From: Sebastian <15335529+Sobeston@users.noreply.github.com> Date: Wed, 1 Apr 2020 09:11:05 +0100 Subject: [PATCH 01/74] mem.zeroes - add sentinel terminated array support --- lib/std/mem.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index f54eb03d65..cedb1bc27d 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -341,6 +341,9 @@ pub fn zeroes(comptime T: type) T { } }, .Array => |info| { + if (info.sentinel) |sentinel| { + return [_:info.sentinel]info.child{zeroes(info.child)} ** info.len; + } return [_]info.child{zeroes(info.child)} ** info.len; }, .Vector, From ebbd137a0e90a8e78655d2a5f74cf87120b5a5a1 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Tue, 21 Apr 2020 10:25:09 +0200 Subject: [PATCH 02/74] fix json.WriteStream.emitJson --- lib/std/json/write_stream.zig | 55 ++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig index 60974a207e..11f0171996 100644 --- a/lib/std/json/write_stream.zig +++ b/lib/std/json/write_stream.zig @@ -148,6 +148,7 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { self.popState(); } + // TODO better handling of ComptimeInt and ComptimeFloat pub fn emitNumber( self: *Self, /// An integer, float, or `std.math.BigInt`. Emitted as a bare number if it fits losslessly @@ -180,6 +181,7 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { } pub fn emitString(self: *Self, string: []const u8) !void { + assert(self.state[self.state_index] == State.Value); try self.writeEscapedString(string); self.popState(); } @@ -191,7 +193,9 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { /// Writes the complete json into the output stream pub fn emitJson(self: *Self, json: std.json.Value) Stream.Error!void { + assert(self.state[self.state_index] == State.Value); try self.stringify(json); + self.popState(); } fn indent(self: *Self) !void { @@ -233,7 +237,32 @@ test "json write stream" { defer arena_allocator.deinit(); var w = std.json.writeStream(out, 10); - try w.emitJson(try getJson(&arena_allocator.allocator)); + + try w.beginObject(); + + try w.objectField("object"); + try w.emitJson(try getJsonObject(&arena_allocator.allocator)); + + try w.objectField("string"); + try w.emitString("This is a string"); + + try w.objectField("array"); + try w.beginArray(); + try w.arrayElem(); + try w.emitString("Another string"); + try w.arrayElem(); + try w.emitNumber(@as(i32, 1)); + try w.arrayElem(); + try w.emitNumber(@as(f32, 3.5)); + try w.endArray(); + + try w.objectField("int"); + try w.emitNumber(@as(i32, 10)); + + try w.objectField("float"); + try w.emitNumber(@as(f32, 3.5)); + + try w.endObject(); const result = slice_stream.getWritten(); const expected = @@ -246,38 +275,18 @@ test "json write stream" { \\ "array": [ \\ "Another string", \\ 1, - \\ 3.14e+00 + \\ 3.5e+00 \\ ], \\ "int": 10, - \\ "float": 3.14e+00 + \\ "float": 3.5e+00 \\} ; std.testing.expect(std.mem.eql(u8, expected, result)); } -fn getJson(allocator: *std.mem.Allocator) !std.json.Value { - var value = std.json.Value{ .Object = std.json.ObjectMap.init(allocator) }; - _ = try value.Object.put("string", std.json.Value{ .String = "This is a string" }); - _ = try value.Object.put("int", std.json.Value{ .Integer = @intCast(i64, 10) }); - _ = try value.Object.put("float", std.json.Value{ .Float = 3.14 }); - _ = try value.Object.put("array", try getJsonArray(allocator)); - _ = try value.Object.put("object", try getJsonObject(allocator)); - return value; -} - fn getJsonObject(allocator: *std.mem.Allocator) !std.json.Value { var value = std.json.Value{ .Object = std.json.ObjectMap.init(allocator) }; _ = try value.Object.put("one", std.json.Value{ .Integer = @intCast(i64, 1) }); _ = try value.Object.put("two", std.json.Value{ .Float = 2.0 }); return value; } - -fn getJsonArray(allocator: *std.mem.Allocator) !std.json.Value { - var value = std.json.Value{ .Array = std.json.Array.init(allocator) }; - var array = &value.Array; - _ = try array.append(std.json.Value{ .String = "Another string" }); - _ = try array.append(std.json.Value{ .Integer = @intCast(i64, 1) }); - _ = try array.append(std.json.Value{ .Float = 3.14 }); - - return value; -} From 3a397795be1c0219a3a0d96082ee7d4eeddbfa7a Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sat, 2 May 2020 23:28:44 +0200 Subject: [PATCH 03/74] Apply naming conventions of structs to files --- doc/langref.html.in | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/langref.html.in b/doc/langref.html.in index 6026912893..537a0a55d3 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -9990,6 +9990,13 @@ coding style. conventions.

+ File names fall into two categories: types and namespaces. If the file + (implicity a struct) has top level fields, it should be named like any + other struct with fields using {#syntax#}TitleCase{#endsyntax#}. Otherwise, + it should use {#syntax#}snake_case{#endsyntax#}. Directory names should be + {#syntax#}snake_case{#endsyntax#}. +

+

These are general rules of thumb; if it makes sense to do something different, do what makes sense. For example, if there is an established convention such as {#syntax#}ENOENT{#endsyntax#}, follow the established convention. @@ -9998,6 +10005,7 @@ coding style. {#header_open|Examples#} {#code_begin|syntax#} const namespace_name = @import("dir_name/file_name.zig"); +const TypeName = @import("dir_name/TypeName.zig"); var global_var: i32 = undefined; const const_name = 42; const primitive_type_alias = f32; From c5198bd76f96d7dab64fdd8d81fc8028187b1403 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Sat, 2 May 2020 20:22:43 -0700 Subject: [PATCH 04/74] added scoped typedef to translate-c --- src-self-hosted/translate_c.zig | 18 ++++++++++++++++++ test/run_translated_c.zig | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 1c689e9f76..a204469b83 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -1394,6 +1394,24 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) node.semicolon_token = try appendToken(c, .Semicolon, ";"); try block_scope.block_node.statements.push(&node.base); }, + .Typedef => { + const type_decl = @ptrCast(*const ZigClangTypedefNameDecl, it[0]); + const name = try c.str(ZigClangNamedDecl_getName_bytes_begin( + @ptrCast(*const ZigClangNamedDecl, type_decl), + )); + + const underlying_qual = ZigClangTypedefNameDecl_getUnderlyingType(type_decl); + const underlying_type = ZigClangQualType_getTypePtr(underlying_qual); + + const mangled_name = try block_scope.makeMangledName(c, name); + const node = try transCreateNodeVarDecl(c, false, true, mangled_name); + node.eq_token = try appendToken(c, .Equal, "="); + + const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)); + node.init_node = try transType(rp, underlying_type, loc); + node.semicolon_token = try appendToken(c, .Semicolon, ";"); + try block_scope.block_node.statements.push(&node.base); + }, else => |kind| return revertAndWarn( rp, error.UnsupportedTranslation, diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index ec6a11b9b4..a49fef76d1 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -243,4 +243,15 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("scoped typedef", + \\int main(int argc, char **argv) { + \\ typedef int Foo; + \\ typedef Foo Bar; + \\ typedef void (*func)(int); + \\ Foo i; + \\ Bar j; + \\ return 0; + \\} + , ""); } From 9b788b765c1557a414710872fa9c11fce1f8c504 Mon Sep 17 00:00:00 2001 From: Cato Date: Sun, 3 May 2020 10:40:07 +0200 Subject: [PATCH 05/74] Pass filtered_sock_type to system.socket. Cover PermissionDenied error --- lib/std/net.zig | 4 ++++ lib/std/net/test.zig | 2 +- lib/std/os.zig | 10 +++++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/std/net.zig b/lib/std/net.zig index b9681bc618..cc3e0d903e 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -1366,6 +1366,10 @@ pub const StreamServer = struct { /// Firewall rules forbid connection. BlockedByFirewall, + + /// Permission to create a socket of the specified type and/or + /// protocol is denied. + PermissionDenied, } || os.UnexpectedError; pub const Connection = struct { diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 087f965c4e..f4f97d3944 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -81,7 +81,7 @@ test "resolve DNS" { test "listen on a port, send bytes, receive bytes" { if (!std.io.is_async) return error.SkipZigTest; - if (std.builtin.os.tag != .linux) { + if (std.builtin.os.tag != .linux and !std.builtin.os.tag.isDarwin()) { // TODO build abstractions for other operating systems return error.SkipZigTest; } diff --git a/lib/std/os.zig b/lib/std/os.zig index ff7089ceb0..3b8767bdc1 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2156,6 +2156,9 @@ pub const SocketError = error{ /// The protocol type or the specified protocol is not supported within this domain. ProtocolNotSupported, + + /// The socket type is not supported by the protocol. + SocketTypeNotSupported, } || UnexpectedError; pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t { @@ -2164,7 +2167,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t { socket_type & ~@as(u32, SOCK_NONBLOCK | SOCK_CLOEXEC) else socket_type; - const rc = system.socket(domain, socket_type, protocol); + const rc = system.socket(domain, filtered_sock_type, protocol); switch (errno(rc)) { 0 => { const fd = @intCast(fd_t, rc); @@ -2181,6 +2184,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t { ENOBUFS => return error.SystemResources, ENOMEM => return error.SystemResources, EPROTONOSUPPORT => return error.ProtocolNotSupported, + EPROTOTYPE => return error.SocketTypeNotSupported, else => |err| return unexpectedErrno(err), } } @@ -2290,6 +2294,10 @@ pub const AcceptError = error{ /// This error occurs when no global event loop is configured, /// and accepting from the socket would block. WouldBlock, + + /// Permission to create a socket of the specified type and/or + /// protocol is denied. + PermissionDenied, } || UnexpectedError; /// Accept a connection on a socket. From adc444ceeb91c06a6ee84dc4e4874294a41dee45 Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 4 May 2020 14:28:58 +0300 Subject: [PATCH 06/74] fix missing compile error on call assigned to const --- src/ir.cpp | 10 ++++++++++ test/compile_errors.zig | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 4795645544..b636ac6f76 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -20000,6 +20000,11 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } + if (result_loc->value->type->data.pointer.is_const) { + ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); + return ira->codegen->invalid_inst_gen; + } + IrInstGen *dummy_value = ir_const(ira, source_instr, impl_fn_type_id->return_type); dummy_value->value->special = ConstValSpecialRuntime; IrInstGen *dummy_result = ir_implicit_cast2(ira, source_instr, @@ -20138,6 +20143,11 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { return result_loc; } + if (result_loc->value->type->data.pointer.is_const) { + ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant")); + return ira->codegen->invalid_inst_gen; + } + IrInstGen *dummy_value = ir_const(ira, source_instr, return_type); dummy_value->value->special = ConstValSpecialRuntime; IrInstGen *dummy_result = ir_implicit_cast2(ira, source_instr, diff --git a/test/compile_errors.zig b/test/compile_errors.zig index fd27b8e666..3d7677ab75 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -2,6 +2,29 @@ const tests = @import("tests.zig"); const std = @import("std"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add("call assigned to constant", + \\const Foo = struct { + \\ x: i32, + \\}; + \\fn foo() Foo { + \\ return .{ .x = 42 }; + \\} + \\fn bar(val: var) Foo { + \\ return .{ .x = val }; + \\} + \\export fn entry() void { + \\ const baz: Foo = undefined; + \\ baz = foo(); + \\} + \\export fn entry1() void { + \\ const baz: Foo = undefined; + \\ baz = bar(42); + \\} + , &[_][]const u8{ + "tmp.zig:12:14: error: cannot assign to constant", + "tmp.zig:16:14: error: cannot assign to constant", + }); + cases.add("invalid pointer syntax", \\export fn foo() void { \\ var guid: *:0 const u8 = undefined; From 85fd484f0778b5f158dc76bf51b820314b86292d Mon Sep 17 00:00:00 2001 From: Vexu Date: Mon, 4 May 2020 14:45:36 +0300 Subject: [PATCH 07/74] std: fix blake3 assignment to constant --- lib/std/crypto/blake3.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/std/crypto/blake3.zig b/lib/std/crypto/blake3.zig index 7c79ffcf55..08479d65a5 100644 --- a/lib/std/crypto/blake3.zig +++ b/lib/std/crypto/blake3.zig @@ -338,7 +338,7 @@ pub const Blake3 = struct { } // Section 5.1.2 of the BLAKE3 spec explains this algorithm in more detail. - fn add_chunk_chaining_value(self: *Blake3, new_cv: [8]u32, total_chunks: u64) void { + fn add_chunk_chaining_value(self: *Blake3, first_cv: [8]u32, total_chunks: u64) void { // This chunk might complete some subtrees. For each completed subtree, // its left child will be the current top entry in the CV stack, and // its right child will be the current value of `new_cv`. Pop each left @@ -346,6 +346,7 @@ pub const Blake3 = struct { // with the result. After all these merges, push the final value of // `new_cv` onto the stack. The number of completed subtrees is given // by the number of trailing 0-bits in the new total number of chunks. + var new_cv = first_cv; var chunk_counter = total_chunks; while (chunk_counter & 1 == 0) { new_cv = parent_cv(self.pop_cv(), new_cv, self.key, self.flags); From 75b699b2c624d62a4b6717f00bd0856b86c3f990 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Mon, 4 May 2020 00:42:12 -0600 Subject: [PATCH 08/74] os.zig: add ETIMEDOUT error case to read function According to documentation ETIMEDOUT (110) is a valid error code for the read function. I just had my long-running (been running for about 7 weeks) network program crash because it did not handle the ETIMEDOUT error code from "read". --- lib/std/os.zig | 2 ++ lib/std/zig/system.zig | 1 + src-self-hosted/stage2.zig | 1 + 3 files changed, 4 insertions(+) diff --git a/lib/std/os.zig b/lib/std/os.zig index 3b8767bdc1..86130ed32c 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -292,6 +292,7 @@ pub const ReadError = error{ OperationAborted, BrokenPipe, ConnectionResetByPeer, + ConnectionTimedOut, /// This error occurs when no global event loop is configured, /// and reading from the file descriptor would block. @@ -351,6 +352,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { ENOBUFS => return error.SystemResources, ENOMEM => return error.SystemResources, ECONNRESET => return error.ConnectionResetByPeer, + ETIMEDOUT => return error.ConnectionTimedOut, else => |err| return unexpectedErrno(err), } } diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 7b05e3bcfb..92f01c4195 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -837,6 +837,7 @@ pub const NativeTargetInfo = struct { error.BrokenPipe => return error.UnableToReadElfFile, error.Unseekable => return error.UnableToReadElfFile, error.ConnectionResetByPeer => return error.UnableToReadElfFile, + error.ConnectionTimedOut => return error.UnableToReadElfFile, error.Unexpected => return error.Unexpected, error.InputOutput => return error.FileSystem, }; diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig index 38ab49ccc4..d93d069915 100644 --- a/src-self-hosted/stage2.zig +++ b/src-self-hosted/stage2.zig @@ -841,6 +841,7 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [ error.EndOfStream => return .EndOfFile, error.IsDir => return .IsDir, error.ConnectionResetByPeer => unreachable, + error.ConnectionTimedOut => unreachable, error.OutOfMemory => return .OutOfMemory, error.Unseekable => unreachable, error.SharingViolation => return .SharingViolation, From db4833d4d607a91686dc37ed68e453e9538dc668 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Mon, 4 May 2020 23:45:31 -0700 Subject: [PATCH 09/74] moved duplicated code to common functions --- src-self-hosted/translate_c.zig | 66 ++++++++++++++++++--------------- test/run_translated_c.zig | 2 + 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index a204469b83..2a8817977b 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -668,17 +668,7 @@ fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const ZigClangTypedefNameDe return transCreateNodeIdentifier(c, builtin_name); } -fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node { - if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv| - return transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice - const rp = makeRestorePoint(c); - - const typedef_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, typedef_decl))); - - // TODO https://github.com/ziglang/zig/issues/3756 - // TODO https://github.com/ziglang/zig/issues/1802 - const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; - +fn checkForBuiltinTypedef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, checked_name: []const u8) !?*ast.Node { if (mem.eql(u8, checked_name, "uint8_t")) return transTypeDefAsBuiltin(c, typedef_decl, "u8") else if (mem.eql(u8, checked_name, "int8_t")) @@ -704,28 +694,49 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l else if (mem.eql(u8, checked_name, "size_t")) return transTypeDefAsBuiltin(c, typedef_decl, "usize"); + return null; +} + +fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_level_visit: bool) Error!?*ast.Node { + if (c.decl_table.get(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)))) |kv| + return transCreateNodeIdentifier(c, kv.value); // Avoid processing this decl twice + const rp = makeRestorePoint(c); + + const typedef_name = try c.str(ZigClangNamedDecl_getName_bytes_begin(@ptrCast(*const ZigClangNamedDecl, typedef_decl))); + + // TODO https://github.com/ziglang/zig/issues/3756 + // TODO https://github.com/ziglang/zig/issues/1802 + const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; + if (try checkForBuiltinTypedef(c, typedef_decl, checked_name)) |node| { + return node; + } + if (!top_level_visit) { return transCreateNodeIdentifier(c, checked_name); } _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name); - const visib_tok = try appendToken(c, .Keyword_pub, "pub"); - const const_tok = try appendToken(c, .Keyword_const, "const"); - const node = try transCreateNodeVarDecl(c, true, true, checked_name); - node.eq_token = try appendToken(c, .Equal, "="); + const node = (try transZigTypedef(rp, typedef_decl, true, checked_name)) orelse return null; + try addTopLevelDecl(c, checked_name, &node.base); + return transCreateNodeIdentifier(c, checked_name); +} + +fn transZigTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedefNameDecl, toplevel: bool, checked_name: []const u8) Error!?*ast.Node.VarDecl { + const node = try transCreateNodeVarDecl(rp.c, toplevel, true, checked_name); + node.eq_token = try appendToken(rp.c, .Equal, "="); const child_qt = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); const typedef_loc = ZigClangTypedefNameDecl_getLocation(typedef_decl); node.init_node = transQualType(rp, child_qt, typedef_loc) catch |err| switch (err) { error.UnsupportedType => { - try failDecl(c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); + try failDecl(rp.c, typedef_loc, checked_name, "unable to resolve typedef child type", .{}); return null; }, error.OutOfMemory => |e| return e, }; - node.semicolon_token = try appendToken(c, .Semicolon, ";"); - try addTopLevelDecl(c, checked_name, &node.base); - return transCreateNodeIdentifier(c, checked_name); + + node.semicolon_token = try appendToken(rp.c, .Semicolon, ";"); + return node; } fn transRecordDecl(c: *Context, record_decl: *const ZigClangRecordDecl) Error!?*ast.Node { @@ -1395,21 +1406,18 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) try block_scope.block_node.statements.push(&node.base); }, .Typedef => { - const type_decl = @ptrCast(*const ZigClangTypedefNameDecl, it[0]); + const typedef_decl = @ptrCast(*const ZigClangTypedefNameDecl, it[0]); const name = try c.str(ZigClangNamedDecl_getName_bytes_begin( - @ptrCast(*const ZigClangNamedDecl, type_decl), + @ptrCast(*const ZigClangNamedDecl, typedef_decl), )); - const underlying_qual = ZigClangTypedefNameDecl_getUnderlyingType(type_decl); - const underlying_type = ZigClangQualType_getTypePtr(underlying_qual); - const mangled_name = try block_scope.makeMangledName(c, name); - const node = try transCreateNodeVarDecl(c, false, true, mangled_name); - node.eq_token = try appendToken(c, .Equal, "="); + if (try checkForBuiltinTypedef(c, typedef_decl, mangled_name)) |ast_node| { + return ast_node; + } - const loc = ZigClangStmt_getBeginLoc(@ptrCast(*const ZigClangStmt, stmt)); - node.init_node = try transType(rp, underlying_type, loc); - node.semicolon_token = try appendToken(c, .Semicolon, ";"); + const node = (try transZigTypedef(rp, typedef_decl, false, mangled_name)) + orelse return error.UnsupportedTranslation; try block_scope.block_node.statements.push(&node.base); }, else => |kind| return revertAndWarn( diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index a49fef76d1..83569f1241 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -245,10 +245,12 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { , ""); cases.add("scoped typedef", + \\#include \\int main(int argc, char **argv) { \\ typedef int Foo; \\ typedef Foo Bar; \\ typedef void (*func)(int); + \\ typedef uint32_t Number; \\ Foo i; \\ Bar j; \\ return 0; From 4cb4097b084d9f9df31d7cf36b5876ad51790828 Mon Sep 17 00:00:00 2001 From: Haze Booth Date: Tue, 5 May 2020 04:14:11 -0400 Subject: [PATCH 10/74] Update ErrorUnion thread spawn result to return null instead of 0 --- lib/std/thread.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/thread.zig b/lib/std/thread.zig index 6d9b4bebe6..d07c41c5b0 100644 --- a/lib/std/thread.zig +++ b/lib/std/thread.zig @@ -280,7 +280,7 @@ pub const Thread = struct { std.debug.dumpStackTrace(trace.*); } }; - return 0; + return null; }, else => @compileError(bad_startfn_ret), } From 8d5636ebe4b1d70db14e28c67f7986fb2a1ce3cf Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 5 May 2020 05:08:46 -0600 Subject: [PATCH 11/74] Rename noasync to nosuspend in self-hosted, add rewriter --- doc/docgen.zig | 2 +- lib/std/zig/ast.zig | 22 +++++++++++----------- lib/std/zig/parse.zig | 24 ++++++++++++------------ lib/std/zig/parser_test.zig | 26 ++++++++++++++++++++------ lib/std/zig/render.zig | 14 +++++++++----- lib/std/zig/tokenizer.zig | 7 ++++--- 6 files changed, 57 insertions(+), 38 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index 21bec3ba7e..a249a526a1 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -802,8 +802,8 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .Keyword_inline, .Keyword_nakedcc, .Keyword_noalias, - .Keyword_noasync, .Keyword_noinline, + .Keyword_nosuspend, .Keyword_or, .Keyword_orelse, .Keyword_packed, diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 91b9a704c9..50051040d9 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -438,7 +438,7 @@ pub const Node = struct { ContainerDecl, Asm, Comptime, - Noasync, + Nosuspend, Block, // Misc @@ -569,9 +569,9 @@ pub const Node = struct { return true; }, - .Noasync => { - const noasync_node = @fieldParentPtr(Noasync, "base", n); - return noasync_node.expr.id != .Block; + .Nosuspend => { + const nosuspend_node = @fieldParentPtr(Nosuspend, "base", n); + return nosuspend_node.expr.id != .Block; }, else => return true, } @@ -1084,12 +1084,12 @@ pub const Node = struct { } }; - pub const Noasync = struct { - base: Node = Node{ .id = .Noasync }, - noasync_token: TokenIndex, + pub const Nosuspend = struct { + base: Node = Node{ .id = .Nosuspend }, + nosuspend_token: TokenIndex, expr: *Node, - pub fn iterate(self: *Noasync, index: usize) ?*Node { + pub fn iterate(self: *Nosuspend, index: usize) ?*Node { var i = index; if (i < 1) return self.expr; @@ -1098,11 +1098,11 @@ pub const Node = struct { return null; } - pub fn firstToken(self: *const Noasync) TokenIndex { - return self.noasync_token; + pub fn firstToken(self: *const Nosuspend) TokenIndex { + return self.nosuspend_token; } - pub fn lastToken(self: *const Noasync) TokenIndex { + pub fn lastToken(self: *const Nosuspend) TokenIndex { return self.expr.lastToken(); } }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index fdaf0ec8f1..d7f4d76cf6 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -495,7 +495,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No /// Statement /// <- KEYWORD_comptime? VarDecl /// / KEYWORD_comptime BlockExprStatement -/// / KEYWORD_noasync BlockExprStatement +/// / KEYWORD_nosuspend BlockExprStatement /// / KEYWORD_suspend (SEMICOLON / BlockExprStatement) /// / KEYWORD_defer BlockExprStatement /// / KEYWORD_errdefer Payload? BlockExprStatement @@ -527,14 +527,14 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No return &node.base; } - if (eatToken(it, .Keyword_noasync)) |noasync_token| { + if (eatToken(it, .Keyword_nosuspend)) |nosuspend_token| { const block_expr = try expectNode(arena, it, tree, parseBlockExprStatement, .{ .ExpectedBlockOrAssignment = .{ .token = it.index }, }); - const node = try arena.create(Node.Noasync); + const node = try arena.create(Node.Nosuspend); node.* = .{ - .noasync_token = noasync_token, + .nosuspend_token = nosuspend_token, .expr = block_expr, }; return &node.base; @@ -908,7 +908,7 @@ fn parsePrefixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { /// / IfExpr /// / KEYWORD_break BreakLabel? Expr? /// / KEYWORD_comptime Expr -/// / KEYWORD_noasync Expr +/// / KEYWORD_nosuspend Expr /// / KEYWORD_continue BreakLabel? /// / KEYWORD_resume Expr /// / KEYWORD_return Expr? @@ -944,13 +944,13 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node return &node.base; } - if (eatToken(it, .Keyword_noasync)) |token| { + if (eatToken(it, .Keyword_nosuspend)) |token| { const expr_node = try expectNode(arena, it, tree, parseExpr, .{ .ExpectedExpr = .{ .token = it.index }, }); - const node = try arena.create(Node.Noasync); + const node = try arena.create(Node.Nosuspend); node.* = .{ - .noasync_token = token, + .nosuspend_token = token, .expr = expr_node, }; return &node.base; @@ -1288,7 +1288,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { /// / IfTypeExpr /// / INTEGER /// / KEYWORD_comptime TypeExpr -/// / KEYWORD_noasync TypeExpr +/// / KEYWORD_nosuspend TypeExpr /// / KEYWORD_error DOT IDENTIFIER /// / KEYWORD_false /// / KEYWORD_null @@ -1327,11 +1327,11 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N }; return &node.base; } - if (eatToken(it, .Keyword_noasync)) |token| { + if (eatToken(it, .Keyword_nosuspend)) |token| { const expr = (try parseTypeExpr(arena, it, tree)) orelse return null; - const node = try arena.create(Node.Noasync); + const node = try arena.create(Node.Nosuspend); node.* = .{ - .noasync_token = token, + .nosuspend_token = token, .expr = expr, }; return &node.base; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 7fca72ac70..ebc6b92b78 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -35,10 +35,10 @@ test "zig fmt: errdefer with payload" { ); } -test "zig fmt: noasync block" { +test "zig fmt: nosuspend block" { try testCanonical( \\pub fn main() anyerror!void { - \\ noasync { + \\ nosuspend { \\ var foo: Foo = .{ .bar = 42 }; \\ } \\} @@ -46,10 +46,10 @@ test "zig fmt: noasync block" { ); } -test "zig fmt: noasync await" { +test "zig fmt: nosuspend await" { try testCanonical( \\fn foo() void { - \\ x = noasync await y; + \\ x = nosuspend await y; \\} \\ ); @@ -2519,9 +2519,9 @@ test "zig fmt: async functions" { ); } -test "zig fmt: noasync" { +test "zig fmt: nosuspend" { try testCanonical( - \\const a = noasync foo(); + \\const a = nosuspend foo(); \\ ); } @@ -2926,6 +2926,20 @@ test "zig fmt: hexadeciaml float literals with underscore separators" { ); } +test "zig fmt: noasync to nosuspend" { + // TODO: remove this + try testTransform( + \\pub fn main() void { + \\ noasync call(); + \\} + , + \\pub fn main() void { + \\ nosuspend call(); + \\} + \\ + ); +} + const std = @import("std"); const mem = std.mem; const warn = std.debug.warn; diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 1e1552dae4..441a91a28a 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -391,11 +391,15 @@ fn renderExpression( try renderToken(tree, stream, comptime_node.comptime_token, indent, start_col, Space.Space); return renderExpression(allocator, stream, tree, indent, start_col, comptime_node.expr, space); }, - .Noasync => { - const noasync_node = @fieldParentPtr(ast.Node.Noasync, "base", base); - - try renderToken(tree, stream, noasync_node.noasync_token, indent, start_col, Space.Space); - return renderExpression(allocator, stream, tree, indent, start_col, noasync_node.expr, space); + .Nosuspend => { + const nosuspend_node = @fieldParentPtr(ast.Node.Nosuspend, "base", base); + if (mem.eql(u8, tree.tokenSlice(nosuspend_node.nosuspend_token), "noasync")) { + // TODO: remove this + try stream.writeAll("nosuspend "); + } else { + try renderToken(tree, stream, nosuspend_node.nosuspend_token, indent, start_col, Space.Space); + } + return renderExpression(allocator, stream, tree, indent, start_col, nosuspend_node.expr, space); }, .Suspend => { diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index 99574f2a98..b6c1a06276 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -49,8 +49,9 @@ pub const Token = struct { Keyword.init("inline", .Keyword_inline), Keyword.init("nakedcc", .Keyword_nakedcc), Keyword.init("noalias", .Keyword_noalias), - Keyword.init("noasync", .Keyword_noasync), + Keyword.init("noasync", .Keyword_nosuspend), // TODO: remove this Keyword.init("noinline", .Keyword_noinline), + Keyword.init("nosuspend", .Keyword_nosuspend), Keyword.init("null", .Keyword_null), Keyword.init("or", .Keyword_or), Keyword.init("orelse", .Keyword_orelse), @@ -182,8 +183,8 @@ pub const Token = struct { Keyword_inline, Keyword_nakedcc, Keyword_noalias, - Keyword_noasync, Keyword_noinline, + Keyword_nosuspend, Keyword_null, Keyword_or, Keyword_orelse, @@ -307,8 +308,8 @@ pub const Token = struct { .Keyword_inline => "inline", .Keyword_nakedcc => "nakedcc", .Keyword_noalias => "noalias", - .Keyword_noasync => "noasync", .Keyword_noinline => "noinline", + .Keyword_nosuspend => "nosuspend", .Keyword_null => "null", .Keyword_or => "or", .Keyword_orelse => "orelse", From b957dc29a4e3f025e446e717b0ae8c69602545ca Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 5 May 2020 05:11:19 -0600 Subject: [PATCH 12/74] Rename noasync to nosuspend in C++ compiler --- src/all_types.hpp | 22 ++++++++--------- src/analyze.cpp | 18 +++++++------- src/analyze.hpp | 2 +- src/ast_render.cpp | 14 +++++------ src/codegen.cpp | 30 +++++++++++------------ src/ir.cpp | 60 +++++++++++++++++++++++----------------------- src/ir_print.cpp | 8 +++---- src/parser.cpp | 32 ++++++++++++------------- src/tokenizer.cpp | 4 ++-- src/tokenizer.hpp | 2 +- 10 files changed, 96 insertions(+), 96 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index ade57a0a5d..aeffa440ab 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -672,7 +672,7 @@ enum NodeType { NodeTypeSwitchProng, NodeTypeSwitchRange, NodeTypeCompTime, - NodeTypeNoAsync, + NodeTypeNoSuspend, NodeTypeBreak, NodeTypeContinue, NodeTypeAsmExpr, @@ -862,7 +862,7 @@ enum CallModifier { CallModifierAsync, CallModifierNeverTail, CallModifierNeverInline, - CallModifierNoAsync, + CallModifierNoSuspend, CallModifierAlwaysTail, CallModifierAlwaysInline, CallModifierCompileTime, @@ -1014,7 +1014,7 @@ struct AstNodeCompTime { AstNode *expr; }; -struct AstNodeNoAsync { +struct AstNodeNoSuspend { AstNode *expr; }; @@ -1225,7 +1225,7 @@ struct AstNode { AstNodeSwitchProng switch_prong; AstNodeSwitchRange switch_range; AstNodeCompTime comptime_expr; - AstNodeNoAsync noasync_expr; + AstNodeNoSuspend nosuspend_expr; AstNodeAsmExpr asm_expr; AstNodeFieldAccessExpr field_access_expr; AstNodePtrDerefExpr ptr_deref_expr; @@ -1858,7 +1858,7 @@ enum PanicMsgId { PanicMsgIdResumedAnAwaitingFn, PanicMsgIdFrameTooSmall, PanicMsgIdResumedFnPendingAwait, - PanicMsgIdBadNoAsyncCall, + PanicMsgIdBadNoSuspendCall, PanicMsgIdResumeNotSuspendedFn, PanicMsgIdBadSentinel, PanicMsgIdShxTooBigRhs, @@ -2376,7 +2376,7 @@ enum ScopeId { ScopeIdRuntime, ScopeIdTypeOf, ScopeIdExpr, - ScopeIdNoAsync, + ScopeIdNoSuspend, }; struct Scope { @@ -2510,9 +2510,9 @@ struct ScopeCompTime { Scope base; }; -// This scope is created for a noasync expression. -// NodeTypeNoAsync -struct ScopeNoAsync { +// This scope is created for a nosuspend expression. +// NodeTypeNoSuspend +struct ScopeNoSuspend { Scope base; }; @@ -4488,7 +4488,7 @@ struct IrInstSrcAwait { IrInstSrc *frame; ResultLoc *result_loc; - bool is_noasync; + bool is_nosuspend; }; struct IrInstGenAwait { @@ -4497,7 +4497,7 @@ struct IrInstGenAwait { IrInstGen *frame; IrInstGen *result_loc; ZigFn *target_fn; - bool is_noasync; + bool is_nosuspend; }; struct IrInstSrcResume { diff --git a/src/analyze.cpp b/src/analyze.cpp index d170273808..4c3103c48c 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -106,7 +106,7 @@ static ScopeExpr *find_expr_scope(Scope *scope) { case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdVarDecl: case ScopeIdCImport: case ScopeIdSuspend: @@ -227,9 +227,9 @@ Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent) { return &scope->base; } -Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent) { - ScopeNoAsync *scope = heap::c_allocator.create(); - init_scope(g, &scope->base, ScopeIdNoAsync, node, parent); +Scope *create_nosuspend_scope(CodeGen *g, AstNode *node, Scope *parent) { + ScopeNoSuspend *scope = heap::c_allocator.create(); + init_scope(g, &scope->base, ScopeIdNoSuspend, node, parent); return &scope->base; } @@ -3771,7 +3771,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeCompTime: preview_comptime_decl(g, node, decls_scope); break; - case NodeTypeNoAsync: + case NodeTypeNoSuspend: case NodeTypeParamDecl: case NodeTypeReturnExpr: case NodeTypeDefer: @@ -4689,7 +4689,7 @@ void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { static Error analyze_callee_async(CodeGen *g, ZigFn *fn, ZigFn *callee, AstNode *call_node, bool must_not_be_async, CallModifier modifier) { - if (modifier == CallModifierNoAsync) + if (modifier == CallModifierNoSuspend) return ErrorNone; bool callee_is_async = false; switch (callee->type_entry->data.fn.fn_type_id.cc) { @@ -4812,7 +4812,7 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) { } for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstGenAwait *await = fn->await_list.at(i); - if (await->is_noasync) continue; + if (await->is_nosuspend) continue; switch (analyze_callee_async(g, fn, await->target_fn, await->base.base.source_node, must_not_be_async, CallModifierNone)) { @@ -6239,7 +6239,7 @@ static void mark_suspension_point(Scope *scope) { case ScopeIdDecls: case ScopeIdFnDef: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdCImport: case ScopeIdSuspend: case ScopeIdTypeOf: @@ -6472,7 +6472,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) { // The funtion call result of foo() must be spilled. for (size_t i = 0; i < fn->await_list.length; i += 1) { IrInstGenAwait *await = fn->await_list.at(i); - if (await->is_noasync) { + if (await->is_nosuspend) { continue; } if (await->base.value->special != ConstValSpecialRuntime) { diff --git a/src/analyze.hpp b/src/analyze.hpp index ae010c87e1..abe1d938d9 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -125,7 +125,7 @@ ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry); Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); -Scope *create_noasync_scope(CodeGen *g, AstNode *node, Scope *parent); +Scope *create_nosuspend_scope(CodeGen *g, AstNode *node, Scope *parent); Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, IrInstSrc *is_comptime); Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 52e450dad4..49fad80a40 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -220,8 +220,8 @@ static const char *node_type_str(NodeType node_type) { return "SwitchRange"; case NodeTypeCompTime: return "CompTime"; - case NodeTypeNoAsync: - return "NoAsync"; + case NodeTypeNoSuspend: + return "NoSuspend"; case NodeTypeBreak: return "Break"; case NodeTypeContinue: @@ -709,8 +709,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { switch (node->data.fn_call_expr.modifier) { case CallModifierNone: break; - case CallModifierNoAsync: - fprintf(ar->f, "noasync "); + case CallModifierNoSuspend: + fprintf(ar->f, "nosuspend "); break; case CallModifierAsync: fprintf(ar->f, "async "); @@ -1093,10 +1093,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { render_node_grouped(ar, node->data.comptime_expr.expr); break; } - case NodeTypeNoAsync: + case NodeTypeNoSuspend: { - fprintf(ar->f, "noasync "); - render_node_grouped(ar, node->data.noasync_expr.expr); + fprintf(ar->f, "nosuspend "); + render_node_grouped(ar, node->data.nosuspend_expr.expr); break; } case NodeTypeForExpr: diff --git a/src/codegen.cpp b/src/codegen.cpp index 366eac4230..bf0e004dda 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -685,7 +685,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -966,8 +966,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { return buf_create_from_str("frame too small"); case PanicMsgIdResumedFnPendingAwait: return buf_create_from_str("resumed an async function which can only be awaited"); - case PanicMsgIdBadNoAsyncCall: - return buf_create_from_str("async function called in noasync scope suspended"); + case PanicMsgIdBadNoSuspendCall: + return buf_create_from_str("async function called in nosuspend scope suspended"); case PanicMsgIdResumeNotSuspendedFn: return buf_create_from_str("resumed a non-suspended function"); case PanicMsgIdBadSentinel: @@ -4061,7 +4061,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) { case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -4212,9 +4212,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn // even if prefix_arg_err_ret_stack is true, let the async function do its own // initialization. } else { - if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { + if (instruction->modifier == CallModifierNoSuspend && !fn_is_async(g->cur_fn)) { // Async function called as a normal function, and calling function is not async. - // This is allowed because it was called with `noasync` which asserts that it will + // This is allowed because it was called with `nosuspend` which asserts that it will // never suspend. awaiter_init_val = zero; } else { @@ -4325,7 +4325,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn case CallModifierCompileTime: zig_unreachable(); case CallModifierNone: - case CallModifierNoAsync: + case CallModifierNoSuspend: case CallModifierAsync: call_attr = ZigLLVM_CallAttrAuto; break; @@ -4401,7 +4401,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn get_llvm_type(g, instruction->base.value->type), ""); } return nullptr; - } else if (instruction->modifier == CallModifierNoAsync && !fn_is_async(g->cur_fn)) { + } else if (instruction->modifier == CallModifierNoSuspend && !fn_is_async(g->cur_fn)) { gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); if (ir_want_runtime_safety(g, &instruction->base)) { @@ -4412,13 +4412,13 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutableGen *executable, IrIn all_ones, LLVMAtomicOrderingRelease); LLVMValueRef ok_val = LLVMBuildICmp(g->builder, LLVMIntEQ, prev_val, all_ones, ""); - LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoAsyncPanic"); - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoAsyncOk"); + LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoSuspendPanic"); + LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "NoSuspendOk"); LLVMBuildCondBr(g->builder, ok_val, ok_block, bad_block); - // The async function suspended, but this noasync call asserted it wouldn't. + // The async function suspended, but this nosuspend call asserted it wouldn't. LLVMPositionBuilderAtEnd(g->builder, bad_block); - gen_safety_crash(g, PanicMsgIdBadNoAsyncCall); + gen_safety_crash(g, PanicMsgIdBadNoSuspendCall); LLVMPositionBuilderAtEnd(g->builder, ok_block); } @@ -6391,7 +6391,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutableGen *executable, IrI LLVMValueRef result_loc = (instruction->result_loc == nullptr) ? nullptr : ir_llvm_value(g, instruction->result_loc); - if (instruction->is_noasync || + if (instruction->is_nosuspend || (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn))) { return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, @@ -7918,7 +7918,7 @@ static void do_code_gen(CodeGen *g) { } if (!is_async) { - // allocate async frames for noasync calls & awaits to async functions + // allocate async frames for nosuspend calls & awaits to async functions ZigType *largest_call_frame_type = nullptr; IrInstGen *all_calls_alloca = ir_create_alloca(g, &fn_table_entry->fndef_scope->base, fn_table_entry->body_node, fn_table_entry, g->builtin_types.entry_void, "@async_call_frame"); @@ -7928,7 +7928,7 @@ static void do_code_gen(CodeGen *g) { continue; if (!fn_is_async(call->fn_entry)) continue; - if (call->modifier != CallModifierNoAsync) + if (call->modifier != CallModifierNoSuspend) continue; if (call->frame_result_loc != nullptr) continue; diff --git a/src/ir.cpp b/src/ir.cpp index f37f91088a..a8243b15df 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4846,12 +4846,12 @@ static IrInstGen *ir_build_suspend_finish_gen(IrAnalyze *ira, IrInst *source_ins } static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *frame, ResultLoc *result_loc, bool is_noasync) + IrInstSrc *frame, ResultLoc *result_loc, bool is_nosuspend) { IrInstSrcAwait *instruction = ir_build_instruction(irb, scope, source_node); instruction->frame = frame; instruction->result_loc = result_loc; - instruction->is_noasync = is_noasync; + instruction->is_nosuspend = is_nosuspend; ir_ref_instruction(frame, irb->current_basic_block); @@ -4859,14 +4859,14 @@ static IrInstSrc *ir_build_await_src(IrBuilderSrc *irb, Scope *scope, AstNode *s } static IrInstGenAwait *ir_build_await_gen(IrAnalyze *ira, IrInst *source_instruction, - IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_noasync) + IrInstGen *frame, ZigType *result_type, IrInstGen *result_loc, bool is_nosuspend) { IrInstGenAwait *instruction = ir_build_inst_gen(&ira->new_irb, source_instruction->scope, source_instruction->source_node); instruction->base.value->type = result_type; instruction->frame = frame; instruction->result_loc = result_loc; - instruction->is_noasync = is_noasync; + instruction->is_nosuspend = is_nosuspend; ir_ref_inst_gen(frame); if (result_loc != nullptr) ir_ref_inst_gen(result_loc); @@ -4982,7 +4982,7 @@ static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_ case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -5072,7 +5072,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope case ScopeIdLoop: case ScopeIdSuspend: case ScopeIdCompTime: - case ScopeIdNoAsync: + case ScopeIdNoSuspend: case ScopeIdRuntime: case ScopeIdTypeOf: case ScopeIdExpr: @@ -7335,10 +7335,10 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod zig_unreachable(); } -static ScopeNoAsync *get_scope_noasync(Scope *scope) { +static ScopeNoSuspend *get_scope_nosuspend(Scope *scope) { while (scope) { - if (scope->id == ScopeIdNoAsync) - return (ScopeNoAsync *)scope; + if (scope->id == ScopeIdNoSuspend) + return (ScopeNoSuspend *)scope; if (scope->id == ScopeIdFnDef) return nullptr; @@ -7355,15 +7355,15 @@ static IrInstSrc *ir_gen_fn_call(IrBuilderSrc *irb, Scope *scope, AstNode *node, if (node->data.fn_call_expr.modifier == CallModifierBuiltin) return ir_gen_builtin_fn_call(irb, scope, node, lval, result_loc); - bool is_noasync = get_scope_noasync(scope) != nullptr; + bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; CallModifier modifier = node->data.fn_call_expr.modifier; - if (is_noasync) { + if (is_nosuspend) { if (modifier == CallModifierAsync) { add_node_error(irb->codegen, node, - buf_sprintf("async call in noasync scope")); + buf_sprintf("async call in nosuspend scope")); return irb->codegen->invalid_inst_src; } - modifier = CallModifierNoAsync; + modifier = CallModifierNoSuspend; } AstNode *fn_ref_node = node->data.fn_call_expr.fn_ref_expr; @@ -9222,10 +9222,10 @@ static IrInstSrc *ir_gen_comptime(IrBuilderSrc *irb, Scope *parent_scope, AstNod return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); } -static IrInstSrc *ir_gen_noasync(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { - assert(node->type == NodeTypeNoAsync); +static IrInstSrc *ir_gen_nosuspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode *node, LVal lval) { + assert(node->type == NodeTypeNoSuspend); - Scope *child_scope = create_noasync_scope(irb->codegen, node, parent_scope); + Scope *child_scope = create_nosuspend_scope(irb->codegen, node, parent_scope); // purposefully pass null for result_loc and let EndExpr handle it return ir_gen_node_extra(irb, node->data.comptime_expr.expr, child_scope, lval, nullptr); } @@ -9813,8 +9813,8 @@ static IrInstSrc *ir_gen_fn_proto(IrBuilderSrc *irb, Scope *parent_scope, AstNod static IrInstSrc *ir_gen_resume(IrBuilderSrc *irb, Scope *scope, AstNode *node) { assert(node->type == NodeTypeResume); - if (get_scope_noasync(scope) != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("resume in noasync scope")); + if (get_scope_nosuspend(scope) != nullptr) { + add_node_error(irb->codegen, node, buf_sprintf("resume in nosuspend scope")); return irb->codegen->invalid_inst_src; } @@ -9830,7 +9830,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no { assert(node->type == NodeTypeAwaitExpr); - bool is_noasync = get_scope_noasync(scope) != nullptr; + bool is_nosuspend = get_scope_nosuspend(scope) != nullptr; AstNode *expr_node = node->data.await_expr.expr; if (expr_node->type == NodeTypeFnCallExpr && expr_node->data.fn_call_expr.modifier == CallModifierBuiltin) { @@ -9864,7 +9864,7 @@ static IrInstSrc *ir_gen_await_expr(IrBuilderSrc *irb, Scope *scope, AstNode *no if (target_inst == irb->codegen->invalid_inst_src) return irb->codegen->invalid_inst_src; - IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_noasync); + IrInstSrc *await_inst = ir_build_await_src(irb, scope, node, target_inst, result_loc, is_nosuspend); return ir_lval_wrap(irb, scope, await_inst, lval, result_loc); } @@ -9876,8 +9876,8 @@ static IrInstSrc *ir_gen_suspend(IrBuilderSrc *irb, Scope *parent_scope, AstNode add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition")); return irb->codegen->invalid_inst_src; } - if (get_scope_noasync(parent_scope) != nullptr) { - add_node_error(irb->codegen, node, buf_sprintf("suspend in noasync scope")); + if (get_scope_nosuspend(parent_scope) != nullptr) { + add_node_error(irb->codegen, node, buf_sprintf("suspend in nosuspend scope")); return irb->codegen->invalid_inst_src; } @@ -10017,8 +10017,8 @@ static IrInstSrc *ir_gen_node_raw(IrBuilderSrc *irb, AstNode *node, Scope *scope return ir_gen_switch_expr(irb, scope, node, lval, result_loc); case NodeTypeCompTime: return ir_expr_wrap(irb, scope, ir_gen_comptime(irb, scope, node, lval), result_loc); - case NodeTypeNoAsync: - return ir_expr_wrap(irb, scope, ir_gen_noasync(irb, scope, node, lval), result_loc); + case NodeTypeNoSuspend: + return ir_expr_wrap(irb, scope, ir_gen_nosuspend(irb, scope, node, lval), result_loc); case NodeTypeErrorType: return ir_lval_wrap(irb, scope, ir_gen_error_type(irb, scope, node), lval, result_loc); case NodeTypeBreak: @@ -10105,7 +10105,7 @@ static IrInstSrc *ir_gen_node_extra(IrBuilderSrc *irb, AstNode *node, Scope *sco case NodeTypeIfOptional: case NodeTypeSwitchExpr: case NodeTypeCompTime: - case NodeTypeNoAsync: + case NodeTypeNoSuspend: case NodeTypeErrorType: case NodeTypeBreak: case NodeTypeContinue: @@ -20025,7 +20025,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if (impl_fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr && - modifier != CallModifierNoAsync) + modifier != CallModifierNoSuspend) { parent_fn_entry->inferred_async_node = fn_ref->base.source_node; parent_fn_entry->inferred_async_fn = impl_fn; @@ -20123,7 +20123,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, if (fn_type_id->cc == CallingConventionAsync && parent_fn_entry->inferred_async_node == nullptr && - modifier != CallModifierNoAsync) + modifier != CallModifierNoSuspend) { parent_fn_entry->inferred_async_node = fn_ref->base.source_node; parent_fn_entry->inferred_async_fn = fn_entry; @@ -20233,7 +20233,7 @@ static IrInstGen *ir_analyze_call_extra(IrAnalyze *ira, IrInst* source_instr, case CallModifierNone: case CallModifierAlwaysInline: case CallModifierAlwaysTail: - case CallModifierNoAsync: + case CallModifierNoSuspend: modifier = CallModifierCompileTime; break; case CallModifierNeverInline: @@ -30277,7 +30277,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i ir_assert(fn_entry != nullptr, &instruction->base.base); // If it's not @Frame(func) then it's definitely a suspend point - if (target_fn == nullptr && !instruction->is_noasync) { + if (target_fn == nullptr && !instruction->is_nosuspend) { if (fn_entry->inferred_async_node == nullptr) { fn_entry->inferred_async_node = instruction->base.base.source_node; } @@ -30301,7 +30301,7 @@ static IrInstGen *ir_analyze_instruction_await(IrAnalyze *ira, IrInstSrcAwait *i } IrInstGenAwait *result = ir_build_await_gen(ira, &instruction->base.base, frame, result_type, result_loc, - instruction->is_noasync); + instruction->is_nosuspend); result->target_fn = target_fn; fn_entry->await_list.append(result); return ir_finish_anal(ira, &result->base); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 6176aaf0ba..3e50b7304f 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -861,8 +861,8 @@ static void ir_print_call_src(IrPrintSrc *irp, IrInstSrcCall *call_instruction) switch (call_instruction->modifier) { case CallModifierNone: break; - case CallModifierNoAsync: - fprintf(irp->f, "noasync "); + case CallModifierNoSuspend: + fprintf(irp->f, "nosuspend "); break; case CallModifierAsync: fprintf(irp->f, "async "); @@ -906,8 +906,8 @@ static void ir_print_call_gen(IrPrintGen *irp, IrInstGenCall *call_instruction) switch (call_instruction->modifier) { case CallModifierNone: break; - case CallModifierNoAsync: - fprintf(irp->f, "noasync "); + case CallModifierNoSuspend: + fprintf(irp->f, "nosuspend "); break; case CallModifierAsync: fprintf(irp->f, "async "); diff --git a/src/parser.cpp b/src/parser.cpp index eed1a5abb4..71f7adf7d1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -913,7 +913,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) { // Statement // <- KEYWORD_comptime? VarDecl // / KEYWORD_comptime BlockExprStatement -// / KEYWORD_noasync BlockExprStatement +// / KEYWORD_nosuspend BlockExprStatement // / KEYWORD_suspend (SEMICOLON / BlockExprStatement) // / KEYWORD_defer BlockExprStatement // / KEYWORD_errdefer Payload? BlockExprStatement @@ -937,11 +937,11 @@ static AstNode *ast_parse_statement(ParseContext *pc) { return res; } - Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync); - if (noasync != nullptr) { + Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); + if (nosuspend != nullptr) { AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement); - AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync); - res->data.noasync_expr.expr = statement; + AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); + res->data.nosuspend_expr.expr = statement; return res; } @@ -1289,7 +1289,7 @@ static AstNode *ast_parse_prefix_expr(ParseContext *pc) { // / IfExpr // / KEYWORD_break BreakLabel? Expr? // / KEYWORD_comptime Expr -// / KEYWORD_noasync Expr +// / KEYWORD_nosuspend Expr // / KEYWORD_continue BreakLabel? // / KEYWORD_resume Expr // / KEYWORD_return Expr? @@ -1324,11 +1324,11 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc) { return res; } - Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync); - if (noasync != nullptr) { + Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); + if (nosuspend != nullptr) { AstNode *expr = ast_expect(pc, ast_parse_expr); - AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync); - res->data.noasync_expr.expr = expr; + AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); + res->data.nosuspend_expr.expr = expr; return res; } @@ -1640,7 +1640,7 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { // / IfTypeExpr // / INTEGER // / KEYWORD_comptime TypeExpr -// / KEYWORD_noasync TypeExpr +// / KEYWORD_nosuspend TypeExpr // / KEYWORD_error DOT IDENTIFIER // / KEYWORD_false // / KEYWORD_null @@ -1742,11 +1742,11 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { return res; } - Token *noasync = eat_token_if(pc, TokenIdKeywordNoAsync); - if (noasync != nullptr) { + Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); + if (nosuspend != nullptr) { AstNode *expr = ast_expect(pc, ast_parse_type_expr); - AstNode *res = ast_create_node(pc, NodeTypeNoAsync, noasync); - res->data.noasync_expr.expr = expr; + AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); + res->data.nosuspend_expr.expr = expr; return res; } @@ -3189,7 +3189,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeCompTime: visit_field(&node->data.comptime_expr.expr, visit, context); break; - case NodeTypeNoAsync: + case NodeTypeNoSuspend: visit_field(&node->data.comptime_expr.expr, visit, context); break; case NodeTypeBreak: diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 11432ecac1..f09a146f2b 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -128,8 +128,8 @@ static const struct ZigKeyword zig_keywords[] = { {"if", TokenIdKeywordIf}, {"inline", TokenIdKeywordInline}, {"noalias", TokenIdKeywordNoAlias}, - {"noasync", TokenIdKeywordNoAsync}, {"noinline", TokenIdKeywordNoInline}, + {"nosuspend", TokenIdKeywordNoSuspend}, {"null", TokenIdKeywordNull}, {"or", TokenIdKeywordOr}, {"orelse", TokenIdKeywordOrElse}, @@ -1589,8 +1589,8 @@ const char * token_name(TokenId id) { case TokenIdKeywordIf: return "if"; case TokenIdKeywordInline: return "inline"; case TokenIdKeywordNoAlias: return "noalias"; - case TokenIdKeywordNoAsync: return "noasync"; case TokenIdKeywordNoInline: return "noinline"; + case TokenIdKeywordNoSuspend: return "nosuspend"; case TokenIdKeywordNull: return "null"; case TokenIdKeywordOr: return "or"; case TokenIdKeywordOrElse: return "orelse"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 3f025ca74a..552ded4ef8 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -78,7 +78,7 @@ enum TokenId { TokenIdKeywordNoInline, TokenIdKeywordLinkSection, TokenIdKeywordNoAlias, - TokenIdKeywordNoAsync, + TokenIdKeywordNoSuspend, TokenIdKeywordNull, TokenIdKeywordOr, TokenIdKeywordOrElse, From af00afed9844b9fb17478d33840fb4a312c4f07c Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 5 May 2020 05:14:22 -0600 Subject: [PATCH 13/74] zig fmt --- lib/std/debug.zig | 30 +++++++-------- lib/std/dwarf.zig | 38 +++++++++---------- lib/std/event/batch.zig | 4 +- lib/std/event/loop.zig | 8 ++-- lib/std/zig/system/macos.zig | 13 +++++-- test/stage1/behavior/async_fn.zig | 10 ++--- test/stage1/behavior/cast.zig | 2 +- .../standalone/main_return_error/error_u8.zig | 4 +- .../main_return_error/error_u8_non_zero.zig | 7 +++- 9 files changed, 61 insertions(+), 55 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index df84a8bbcb..d999de6a17 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -62,7 +62,7 @@ pub fn warn(comptime fmt: []const u8, args: var) void { const held = stderr_mutex.acquire(); defer held.release(); const stderr = getStderrStream(); - noasync stderr.print(fmt, args) catch return; + nosuspend stderr.print(fmt, args) catch return; } pub fn getStderrStream() *File.OutStream { @@ -112,7 +112,7 @@ pub fn detectTTYConfig() TTY.Config { /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { - noasync { + nosuspend { const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; @@ -133,7 +133,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void { /// unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void { - noasync { + nosuspend { const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; @@ -203,7 +203,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void { - noasync { + nosuspend { const stderr = getStderrStream(); if (builtin.strip_debug_info) { stderr.print("Unable to dump stack trace: debug info stripped\n", .{}) catch return; @@ -261,7 +261,7 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c resetSegfaultHandler(); } - noasync switch (panic_stage) { + nosuspend switch (panic_stage) { 0 => { panic_stage = 1; @@ -447,7 +447,7 @@ pub const TTY = struct { windows_api, fn setColor(conf: Config, out_stream: var, color: Color) void { - noasync switch (conf) { + nosuspend switch (conf) { .no_color => return, .escape_codes => switch (color) { .Red => out_stream.writeAll(RED) catch return, @@ -604,7 +604,7 @@ fn printLineInfo( tty_config: TTY.Config, comptime printLineFromFile: var, ) !void { - noasync { + nosuspend { tty_config.setColor(out_stream, .White); if (line_info) |*li| { @@ -651,7 +651,7 @@ pub const OpenSelfDebugInfoError = error{ /// TODO resources https://github.com/ziglang/zig/issues/4353 pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo { - noasync { + nosuspend { if (builtin.strip_debug_info) return error.MissingDebugInfo; if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) { @@ -672,7 +672,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo { /// TODO resources https://github.com/ziglang/zig/issues/4353 fn openCoffDebugInfo(allocator: *mem.Allocator, coff_file_path: [:0]const u16) !ModuleDebugInfo { - noasync { + nosuspend { const coff_file = try std.fs.openFileAbsoluteW(coff_file_path, .{ .intended_io_mode = .blocking }); errdefer coff_file.close(); @@ -853,7 +853,7 @@ fn chopSlice(ptr: []const u8, offset: u64, size: u64) ![]const u8 { /// TODO resources https://github.com/ziglang/zig/issues/4353 pub fn openElfDebugInfo(allocator: *mem.Allocator, elf_file_path: []const u8) !ModuleDebugInfo { - noasync { + nosuspend { const mapped_mem = try mapWholeFile(elf_file_path); const hdr = @ptrCast(*const elf.Ehdr, &mapped_mem[0]); if (!mem.eql(u8, hdr.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic; @@ -1056,7 +1056,7 @@ const MachoSymbol = struct { }; fn mapWholeFile(path: []const u8) ![]align(mem.page_size) const u8 { - noasync { + nosuspend { const file = try fs.cwd().openFile(path, .{ .intended_io_mode = .blocking }); defer file.close(); @@ -1418,7 +1418,7 @@ pub const ModuleDebugInfo = switch (builtin.os.tag) { } fn getSymbolAtAddress(self: *@This(), address: usize) !SymbolInfo { - noasync { + nosuspend { // Translate the VA into an address into this object const relocated_address = address - self.base_address; assert(relocated_address >= 0x100000000); @@ -1643,14 +1643,14 @@ pub const ModuleDebugInfo = switch (builtin.os.tag) { // Translate the VA into an address into this object const relocated_address = address - self.base_address; - if (noasync self.dwarf.findCompileUnit(relocated_address)) |compile_unit| { + if (nosuspend self.dwarf.findCompileUnit(relocated_address)) |compile_unit| { return SymbolInfo{ - .symbol_name = noasync self.dwarf.getSymbolName(relocated_address) orelse "???", + .symbol_name = nosuspend self.dwarf.getSymbolName(relocated_address) orelse "???", .compile_unit_name = compile_unit.die.getAttrString(&self.dwarf, DW.AT_name) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => "???", else => return err, }, - .line_info = noasync self.dwarf.getLineNumberInfo(compile_unit.*, relocated_address) catch |err| switch (err) { + .line_info = nosuspend self.dwarf.getLineNumberInfo(compile_unit.*, relocated_address) catch |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => null, else => return err, }, diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 42139876bb..4191d45d6d 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -252,13 +252,13 @@ fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 { fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { const buf = try allocator.alloc(u8, size); errdefer allocator.free(buf); - if ((try noasync in_stream.read(buf)) < size) return error.EndOfFile; + if ((try nosuspend in_stream.read(buf)) < size) return error.EndOfFile; return buf; } // TODO the noasyncs here are workarounds fn readAddress(in_stream: var, endian: builtin.Endian, is_64: bool) !u64 { - return noasync if (is_64) + return nosuspend if (is_64) try in_stream.readInt(u64, endian) else @as(u64, try in_stream.readInt(u32, endian)); @@ -271,7 +271,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize // TODO the noasyncs here are workarounds fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: usize) !FormValue { - const block_len = try noasync in_stream.readVarInt(usize, endian, size); + const block_len = try nosuspend in_stream.readVarInt(usize, endian, size); return parseFormValueBlockLen(allocator, in_stream, block_len); } @@ -282,16 +282,16 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo .Const = Constant{ .signed = signed, .payload = switch (size) { - 1 => try noasync in_stream.readInt(u8, endian), - 2 => try noasync in_stream.readInt(u16, endian), - 4 => try noasync in_stream.readInt(u32, endian), - 8 => try noasync in_stream.readInt(u64, endian), + 1 => try nosuspend in_stream.readInt(u8, endian), + 2 => try nosuspend in_stream.readInt(u16, endian), + 4 => try nosuspend in_stream.readInt(u32, endian), + 8 => try nosuspend in_stream.readInt(u64, endian), -1 => blk: { if (signed) { - const x = try noasync leb.readILEB128(i64, in_stream); + const x = try nosuspend leb.readILEB128(i64, in_stream); break :blk @bitCast(u64, x); } else { - const x = try noasync leb.readULEB128(u64, in_stream); + const x = try nosuspend leb.readULEB128(u64, in_stream); break :blk x; } }, @@ -305,11 +305,11 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue { return FormValue{ .Ref = switch (size) { - 1 => try noasync in_stream.readInt(u8, endian), - 2 => try noasync in_stream.readInt(u16, endian), - 4 => try noasync in_stream.readInt(u32, endian), - 8 => try noasync in_stream.readInt(u64, endian), - -1 => try noasync leb.readULEB128(u64, in_stream), + 1 => try nosuspend in_stream.readInt(u8, endian), + 2 => try nosuspend in_stream.readInt(u16, endian), + 4 => try nosuspend in_stream.readInt(u32, endian), + 8 => try nosuspend in_stream.readInt(u64, endian), + -1 => try nosuspend leb.readULEB128(u64, in_stream), else => unreachable, }, }; @@ -323,7 +323,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endia FORM_block2 => parseFormValueBlock(allocator, in_stream, endian, 2), FORM_block4 => parseFormValueBlock(allocator, in_stream, endian, 4), FORM_block => x: { - const block_len = try noasync leb.readULEB128(usize, in_stream); + const block_len = try nosuspend leb.readULEB128(usize, in_stream); return parseFormValueBlockLen(allocator, in_stream, block_len); }, FORM_data1 => parseFormValueConstant(allocator, in_stream, false, endian, 1), @@ -335,11 +335,11 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endia return parseFormValueConstant(allocator, in_stream, signed, endian, -1); }, FORM_exprloc => { - const size = try noasync leb.readULEB128(usize, in_stream); + const size = try nosuspend leb.readULEB128(usize, in_stream); const buf = try readAllocBytes(allocator, in_stream, size); return FormValue{ .ExprLoc = buf }; }, - FORM_flag => FormValue{ .Flag = (try noasync in_stream.readByte()) != 0 }, + FORM_flag => FormValue{ .Flag = (try nosuspend in_stream.readByte()) != 0 }, FORM_flag_present => FormValue{ .Flag = true }, FORM_sec_offset => FormValue{ .SecOffset = try readAddress(in_stream, endian, is_64) }, @@ -350,12 +350,12 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endia FORM_ref_udata => parseFormValueRef(allocator, in_stream, endian, -1), FORM_ref_addr => FormValue{ .RefAddr = try readAddress(in_stream, endian, is_64) }, - FORM_ref_sig8 => FormValue{ .Ref = try noasync in_stream.readInt(u64, endian) }, + FORM_ref_sig8 => FormValue{ .Ref = try nosuspend in_stream.readInt(u64, endian) }, FORM_string => FormValue{ .String = try in_stream.readUntilDelimiterAlloc(allocator, 0, math.maxInt(usize)) }, FORM_strp => FormValue{ .StrPtr = try readAddress(in_stream, endian, is_64) }, FORM_indirect => { - const child_form_id = try noasync leb.readULEB128(u64, in_stream); + const child_form_id = try nosuspend leb.readULEB128(u64, in_stream); const F = @TypeOf(async parseFormValue(allocator, in_stream, child_form_id, endian, is_64)); var frame = try allocator.create(F); defer allocator.destroy(frame); diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig index af59b32490..26c0d5fab0 100644 --- a/lib/std/event/batch.zig +++ b/lib/std/event/batch.zig @@ -75,7 +75,7 @@ pub fn Batch( const job = &self.jobs[self.next_job_index]; self.next_job_index = (self.next_job_index + 1) % max_jobs; if (job.frame) |existing| { - job.result = if (async_ok) await existing else noasync await existing; + job.result = if (async_ok) await existing else nosuspend await existing; if (CollectedResult != void) { job.result catch |err| { self.collected_result = err; @@ -94,7 +94,7 @@ pub fn Batch( /// a time, however, it need not be the same thread. pub fn wait(self: *Self) CollectedResult { for (self.jobs) |*job| if (job.frame) |f| { - job.result = if (async_ok) await f else noasync await f; + job.result = if (async_ok) await f else nosuspend await f; if (CollectedResult != void) { job.result catch |err| { self.collected_result = err; diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 6fa65f90dd..15e7a3481c 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -195,7 +195,7 @@ pub const Loop = struct { const wakeup_bytes = [_]u8{0x1} ** 8; fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void { - noasync switch (builtin.os.tag) { + nosuspend switch (builtin.os.tag) { .linux => { errdefer { while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd); @@ -371,7 +371,7 @@ pub const Loop = struct { } fn deinitOsData(self: *Loop) void { - noasync switch (builtin.os.tag) { + nosuspend switch (builtin.os.tag) { .linux => { os.close(self.os_data.final_eventfd); while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd); @@ -663,7 +663,7 @@ pub const Loop = struct { } pub fn finishOneEvent(self: *Loop) void { - noasync { + nosuspend { const prev = @atomicRmw(usize, &self.pending_event_count, .Sub, 1, .SeqCst); if (prev != 1) return; @@ -1041,7 +1041,7 @@ pub const Loop = struct { } fn posixFsRun(self: *Loop) void { - noasync while (true) { + nosuspend while (true) { self.fs_thread_wakeup.reset(); while (self.fs_queue.get()) |node| { switch (node.data.msg) { diff --git a/lib/std/zig/system/macos.zig b/lib/std/zig/system/macos.zig index 3261fdbf4c..dd34fe26f9 100644 --- a/lib/std/zig/system/macos.zig +++ b/lib/std/zig/system/macos.zig @@ -39,7 +39,7 @@ pub fn version_from_build(build: []const u8) !std.builtin.Version { zend += 1; } if (zend == yindex + 1) return error.InvalidVersion; - const z = std.fmt.parseUnsigned(u16, build[yindex + 1..zend], 10) catch return error.InvalidVersion; + const z = std.fmt.parseUnsigned(u16, build[yindex + 1 .. zend], 10) catch return error.InvalidVersion; result.patch = switch (result.minor) { // TODO: compiler complains without explicit @as() coercion @@ -97,7 +97,9 @@ pub fn version_from_build(build: []const u8) !std.builtin.Version { 4 => @as(u32, switch (y) { // Tiger: 10.4 'A' => 0, 'B' => 1, - 'C', 'E', => 2, + 'C', + 'E', + => 2, 'F' => 3, 'G' => @as(u32, block: { if (z >= 1454) break :block 5; @@ -105,7 +107,10 @@ pub fn version_from_build(build: []const u8) !std.builtin.Version { }), 'H' => 5, 'I' => 6, - 'J', 'K', 'N', => 7, + 'J', + 'K', + 'N', + => 7, 'L' => 8, 'P' => 9, 'R' => 10, @@ -438,7 +443,7 @@ test "version_from_build" { for (known) |pair| { var buf: [32]u8 = undefined; const ver = try version_from_build(pair[0]); - const sver = try std.fmt.bufPrint(buf[0..], "{}.{}.{}", .{ver.major, ver.minor, ver.patch}); + const sver = try std.fmt.bufPrint(buf[0..], "{}.{}.{}", .{ ver.major, ver.minor, ver.patch }); std.testing.expect(std.mem.eql(u8, sver, pair[1])); } } diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 958e9ea55f..4b78060664 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1093,7 +1093,7 @@ test "recursive call of await @asyncCall with struct return type" { test "noasync function call" { const S = struct { fn doTheTest() void { - const result = noasync add(50, 100); + const result = nosuspend add(50, 100); expect(result == 150); } fn add(a: i32, b: i32) i32 { @@ -1517,7 +1517,7 @@ test "noasync await" { fn doTheTest() void { var frame = async foo(false); - expect(noasync await frame == 42); + expect(nosuspend await frame == 42); finished = true; } @@ -1544,8 +1544,8 @@ test "noasync on function calls" { return S0{}; } }; - expectEqual(@as(i32, 42), noasync S1.c().b); - expectEqual(@as(i32, 42), (try noasync S1.d()).b); + expectEqual(@as(i32, 42), nosuspend S1.c().b); + expectEqual(@as(i32, 42), (try nosuspend S1.d()).b); } test "avoid forcing frame alignment resolution implicit cast to *c_void" { @@ -1561,5 +1561,5 @@ test "avoid forcing frame alignment resolution implicit cast to *c_void" { }; var frame = async S.foo(); resume @ptrCast(anyframe->bool, @alignCast(@alignOf(@Frame(S.foo)), S.x)); - expect(noasync await frame); + expect(nosuspend await frame); } diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index d277590c7a..63bf055aca 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -823,7 +823,7 @@ test "peer type resolve array pointer and unknown pointer" { comptime expect(@TypeOf(&array, const_ptr) == [*]const u8); comptime expect(@TypeOf(const_ptr, &array) == [*]const u8); - + comptime expect(@TypeOf(&const_array, const_ptr) == [*]const u8); comptime expect(@TypeOf(const_ptr, &const_array) == [*]const u8); } diff --git a/test/standalone/main_return_error/error_u8.zig b/test/standalone/main_return_error/error_u8.zig index 4edac26afd..8fbe1e8f65 100644 --- a/test/standalone/main_return_error/error_u8.zig +++ b/test/standalone/main_return_error/error_u8.zig @@ -1,6 +1,4 @@ -const Err = error { - Foo -}; +const Err = error{Foo}; pub fn main() !u8 { return Err.Foo; diff --git a/test/standalone/main_return_error/error_u8_non_zero.zig b/test/standalone/main_return_error/error_u8_non_zero.zig index 703a19b314..9f7de780ac 100644 --- a/test/standalone/main_return_error/error_u8_non_zero.zig +++ b/test/standalone/main_return_error/error_u8_non_zero.zig @@ -1,6 +1,9 @@ -const Err = error { Foo }; +const Err = error{Foo}; -fn foo() u8 { var x = @intCast(u8, 9); return x; } +fn foo() u8 { + var x = @intCast(u8, 9); + return x; +} pub fn main() !u8 { if (foo() == 7) return Err.Foo; From 2c9204032d1c839d8d577113a9c4def4b9ea9b94 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 5 May 2020 05:18:29 -0600 Subject: [PATCH 14/74] update tests for nosuspend --- test/compile_errors.zig | 10 +++++----- test/runtime_safety.zig | 4 ++-- test/stage1/behavior/async_fn.zig | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index fd27b8e666..c902e1d968 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -243,9 +243,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:17:17: error: RHS of shift is too large for LHS type", }); - cases.addTest("combination of noasync and async", + cases.addTest("combination of nosuspend and async", \\export fn entry() void { - \\ noasync { + \\ nosuspend { \\ const bar = async foo(); \\ suspend; \\ resume bar; @@ -253,9 +253,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\} \\fn foo() void {} , &[_][]const u8{ - "tmp.zig:3:21: error: async call in noasync scope", - "tmp.zig:4:9: error: suspend in noasync scope", - "tmp.zig:5:9: error: resume in noasync scope", + "tmp.zig:3:21: error: async call in nosuspend scope", + "tmp.zig:4:9: error: suspend in nosuspend scope", + "tmp.zig:5:9: error: resume in nosuspend scope", }); cases.add("atomicrmw with bool op not .Xchg", diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 19af470e2f..6837efe2d2 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -234,12 +234,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\} ); - cases.addRuntimeSafety("noasync function call, callee suspends", + cases.addRuntimeSafety("nosuspend function call, callee suspends", \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ @import("std").os.exit(126); \\} \\pub fn main() void { - \\ _ = noasync add(101, 100); + \\ _ = nosuspend add(101, 100); \\} \\fn add(a: i32, b: i32) i32 { \\ if (a > 100) { diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 4b78060664..4f6ace9899 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -1090,7 +1090,7 @@ test "recursive call of await @asyncCall with struct return type" { expect(res.z == 3); } -test "noasync function call" { +test "nosuspend function call" { const S = struct { fn doTheTest() void { const result = nosuspend add(50, 100); @@ -1511,7 +1511,7 @@ test "take address of temporary async frame" { S.doTheTest(); } -test "noasync await" { +test "nosuspend await" { const S = struct { var finished = false; @@ -1532,7 +1532,7 @@ test "noasync await" { expect(S.finished); } -test "noasync on function calls" { +test "nosuspend on function calls" { const S0 = struct { b: i32 = 42, }; From fdfdac493998a180eeffdcab66e579e7af250039 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Tue, 5 May 2020 05:19:17 -0600 Subject: [PATCH 15/74] update comments for nosuspend --- lib/std/dwarf.zig | 12 ++++++------ lib/std/event/batch.zig | 2 +- lib/std/fs/file.zig | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 4191d45d6d..fe40a04b9d 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -248,7 +248,7 @@ fn readUnitLength(in_stream: var, endian: builtin.Endian, is_64: *bool) !u64 { } } -// TODO the noasyncs here are workarounds +// TODO the nosuspends here are workarounds fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { const buf = try allocator.alloc(u8, size); errdefer allocator.free(buf); @@ -256,7 +256,7 @@ fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 return buf; } -// TODO the noasyncs here are workarounds +// TODO the nosuspends here are workarounds fn readAddress(in_stream: var, endian: builtin.Endian, is_64: bool) !u64 { return nosuspend if (is_64) try in_stream.readInt(u64, endian) @@ -269,7 +269,7 @@ fn parseFormValueBlockLen(allocator: *mem.Allocator, in_stream: var, size: usize return FormValue{ .Block = buf }; } -// TODO the noasyncs here are workarounds +// TODO the nosuspends here are workarounds fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: usize) !FormValue { const block_len = try nosuspend in_stream.readVarInt(usize, endian, size); return parseFormValueBlockLen(allocator, in_stream, block_len); @@ -277,7 +277,7 @@ fn parseFormValueBlock(allocator: *mem.Allocator, in_stream: var, endian: builti fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: bool, endian: builtin.Endian, comptime size: i32) !FormValue { // TODO: Please forgive me, I've worked around zig not properly spilling some intermediate values here. - // `noasync` should be removed from all the function calls once it is fixed. + // `nosuspend` should be removed from all the function calls once it is fixed. return FormValue{ .Const = Constant{ .signed = signed, @@ -301,7 +301,7 @@ fn parseFormValueConstant(allocator: *mem.Allocator, in_stream: var, signed: boo }; } -// TODO the noasyncs here are workarounds +// TODO the nosuspends here are workarounds fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin.Endian, size: i32) !FormValue { return FormValue{ .Ref = switch (size) { @@ -315,7 +315,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, endian: builtin. }; } -// TODO the noasyncs here are workarounds +// TODO the nosuspends here are workarounds fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, endian: builtin.Endian, is_64: bool) anyerror!FormValue { return switch (form_id) { FORM_addr => FormValue{ .Address = try readAddress(in_stream, endian, @sizeOf(usize) == 8) }, diff --git a/lib/std/event/batch.zig b/lib/std/event/batch.zig index 26c0d5fab0..9c424fcd2c 100644 --- a/lib/std/event/batch.zig +++ b/lib/std/event/batch.zig @@ -21,7 +21,7 @@ pub fn Batch( /// usual recommended option for this parameter. auto_async, - /// Always uses the `noasync` keyword when using `await` on the jobs, + /// Always uses the `nosuspend` keyword when using `await` on the jobs, /// making `add` and `wait` non-async functions. Asserts that the jobs do not suspend. never_async, diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index b7c575a04a..383a2be12d 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -66,7 +66,7 @@ pub const File = struct { lock_nonblocking: bool = false, /// Setting this to `.blocking` prevents `O_NONBLOCK` from being passed even - /// if `std.io.is_async`. It allows the use of `noasync` when calling functions + /// if `std.io.is_async`. It allows the use of `nosuspend` when calling functions /// related to opening the file, reading, writing, and locking. intended_io_mode: io.ModeOverride = io.default_mode, }; @@ -112,7 +112,7 @@ pub const File = struct { mode: Mode = default_mode, /// Setting this to `.blocking` prevents `O_NONBLOCK` from being passed even - /// if `std.io.is_async`. It allows the use of `noasync` when calling functions + /// if `std.io.is_async`. It allows the use of `nosuspend` when calling functions /// related to opening the file, reading, writing, and locking. intended_io_mode: io.ModeOverride = io.default_mode, }; From 7ada59f873738931b4d162372dff0a33442112b6 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Mon, 4 May 2020 09:06:20 -0600 Subject: [PATCH 16/74] remove nakedcc/stdcallcc/async fn/extern fn fnproto --- doc/docgen.zig | 2 -- doc/langref.html.in | 7 +--- lib/std/zig/ast.zig | 2 -- lib/std/zig/parse.zig | 53 ++---------------------------- lib/std/zig/parser_test.zig | 16 --------- lib/std/zig/render.zig | 24 +------------- lib/std/zig/tokenizer.zig | 6 ---- src-self-hosted/translate_c.zig | 3 -- src/all_types.hpp | 1 - src/analyze.cpp | 2 -- src/parser.cpp | 58 +++------------------------------ 11 files changed, 9 insertions(+), 165 deletions(-) diff --git a/doc/docgen.zig b/doc/docgen.zig index a249a526a1..92a7353fa1 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -800,7 +800,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .Keyword_for, .Keyword_if, .Keyword_inline, - .Keyword_nakedcc, .Keyword_noalias, .Keyword_noinline, .Keyword_nosuspend, @@ -813,7 +812,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok .Keyword_return, .Keyword_linksection, .Keyword_callconv, - .Keyword_stdcallcc, .Keyword_struct, .Keyword_suspend, .Keyword_switch, diff --git a/doc/langref.html.in b/doc/langref.html.in index 6026912893..b2e1f6e6f6 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -10088,7 +10088,7 @@ TopLevelDecl / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl / KEYWORD_usingnamespace Expr SEMICOLON -FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) +FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) VarDecl <- (KEYWORD_const / KEYWORD_var) IDENTIFIER (COLON TypeExpr)? ByteAlign? LinkSection? (EQUAL Expr)? SEMICOLON @@ -10255,11 +10255,6 @@ WhileContinueExpr <- COLON LPAREN AssignExpr RPAREN LinkSection <- KEYWORD_linksection LPAREN Expr RPAREN -# Fn specific -FnCC - <- KEYWORD_extern - / KEYWORD_async - ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType ParamType diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 50051040d9..220b0390f1 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -875,7 +875,6 @@ pub const Node = struct { return_type: ReturnType, var_args_token: ?TokenIndex, extern_export_inline_token: ?TokenIndex, - cc_token: ?TokenIndex, body_node: ?*Node, lib_name: ?*Node, // populated if this is an extern declaration align_expr: ?*Node, // populated if align(A) is present @@ -929,7 +928,6 @@ pub const Node = struct { if (self.visib_token) |visib_token| return visib_token; if (self.extern_export_inline_token) |extern_export_inline_token| return extern_export_inline_token; assert(self.lib_name == null); - if (self.cc_token) |cc_token| return cc_token; return self.fn_token; } diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index d7f4d76cf6..ac1c1f8b15 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -335,22 +335,9 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node return use_node; } -/// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) +/// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { - const cc = parseFnCC(arena, it, tree); - const fn_token = eatToken(it, .Keyword_fn) orelse { - if (cc) |fnCC| { - if (fnCC == .Extern) { - putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl - } else { - try tree.errors.push(.{ - .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn }, - }); - return error.ParseError; - } - } - return null; - }; + const fn_token = eatToken(it, .Keyword_fn) orelse return null; const name_token = eatToken(it, .Identifier); const lparen = try expectToken(it, tree, .LParen); const params = try parseParamDeclList(arena, it, tree); @@ -389,7 +376,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { .return_type = return_type, .var_args_token = var_args_token, .extern_export_inline_token = null, - .cc_token = null, .body_node = null, .lib_name = null, .align_expr = align_expr, @@ -397,13 +383,6 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { .callconv_expr = callconv_expr, }; - if (cc) |kind| { - switch (kind) { - .CC => |token| fn_proto_node.cc_token = token, - .Extern => |token| fn_proto_node.extern_export_inline_token = token, - } - } - return &fn_proto_node.base; } @@ -1196,16 +1175,6 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const maybe_async = eatToken(it, .Keyword_async); if (maybe_async) |async_token| { const token_fn = eatToken(it, .Keyword_fn); - if (token_fn != null) { - // HACK: If we see the keyword `fn`, then we assume that - // we are parsing an async fn proto, and not a call. - // We therefore put back all tokens consumed by the async - // prefix... - putBackToken(it, token_fn.?); - putBackToken(it, async_token); - return parsePrimaryTypeExpr(arena, it, tree); - } - // TODO: Implement hack for parsing `async fn ...` in ast_parse_suffix_expr var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{ .ExpectedPrimaryTypeExpr = .{ .token = it.index }, }); @@ -1778,24 +1747,6 @@ fn parseCallconv(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { return expr_node; } -/// FnCC -/// <- KEYWORD_nakedcc -/// / KEYWORD_stdcallcc -/// / KEYWORD_extern -/// / KEYWORD_async -fn parseFnCC(arena: *Allocator, it: *TokenIterator, tree: *Tree) ?FnCC { - if (eatToken(it, .Keyword_nakedcc)) |token| return FnCC{ .CC = token }; - if (eatToken(it, .Keyword_stdcallcc)) |token| return FnCC{ .CC = token }; - if (eatToken(it, .Keyword_extern)) |token| return FnCC{ .Extern = token }; - if (eatToken(it, .Keyword_async)) |token| return FnCC{ .CC = token }; - return null; -} - -const FnCC = union(enum) { - CC: TokenIndex, - Extern: TokenIndex, -}; - /// ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType fn parseParamDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const doc_comments = try parseDocComment(arena, it, tree); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index ebc6b92b78..198ce1ad94 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -123,22 +123,6 @@ test "zig fmt: trailing comma in fn parameter list" { ); } -// TODO: Remove nakedcc/stdcallcc once zig 0.6.0 is released. See https://github.com/ziglang/zig/pull/3977 -test "zig fmt: convert extern/nakedcc/stdcallcc into callconv(...)" { - try testTransform( - \\nakedcc fn foo1() void {} - \\stdcallcc fn foo2() void {} - \\extern fn foo3() void {} - \\extern "mylib" fn foo4() void {} - , - \\fn foo1() callconv(.Naked) void {} - \\fn foo2() callconv(.Stdcall) void {} - \\fn foo3() callconv(.C) void {} - \\fn foo4() callconv(.C) void {} - \\ - ); -} - test "zig fmt: comptime struct field" { try testCanonical( \\const Foo = struct { diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 441a91a28a..3e2cebcd8a 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1413,32 +1413,14 @@ fn renderExpression( try renderToken(tree, stream, visib_token_index, indent, start_col, Space.Space); // pub } - // Some extra machinery is needed to rewrite the old-style cc - // notation to the new callconv one - var cc_rewrite_str: ?[*:0]const u8 = null; if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - const tok = tree.tokens.at(extern_export_inline_token); - if (tok.id != .Keyword_extern or fn_proto.body_node == null) { - try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export - } else { - cc_rewrite_str = ".C"; - fn_proto.lib_name = null; - } + try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export } if (fn_proto.lib_name) |lib_name| { try renderExpression(allocator, stream, tree, indent, start_col, lib_name, Space.Space); } - if (fn_proto.cc_token) |cc_token| { - var str = tree.tokenSlicePtr(tree.tokens.at(cc_token)); - if (mem.eql(u8, str, "stdcallcc")) { - cc_rewrite_str = ".Stdcall"; - } else if (mem.eql(u8, str, "nakedcc")) { - cc_rewrite_str = ".Naked"; - } else try renderToken(tree, stream, cc_token, indent, start_col, Space.Space); // stdcallcc - } - const lparen = if (fn_proto.name_token) |name_token| blk: { try renderToken(tree, stream, fn_proto.fn_token, indent, start_col, Space.Space); // fn try renderToken(tree, stream, name_token, indent, start_col, Space.None); // name @@ -1528,10 +1510,6 @@ fn renderExpression( try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) - } else if (cc_rewrite_str) |str| { - try stream.writeAll("callconv("); - try stream.writeAll(mem.spanZ(str)); - try stream.writeAll(") "); } switch (fn_proto.return_type) { diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index b6c1a06276..089711871e 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -47,7 +47,6 @@ pub const Token = struct { Keyword.init("for", .Keyword_for), Keyword.init("if", .Keyword_if), Keyword.init("inline", .Keyword_inline), - Keyword.init("nakedcc", .Keyword_nakedcc), Keyword.init("noalias", .Keyword_noalias), Keyword.init("noasync", .Keyword_nosuspend), // TODO: remove this Keyword.init("noinline", .Keyword_noinline), @@ -60,7 +59,6 @@ pub const Token = struct { Keyword.init("resume", .Keyword_resume), Keyword.init("return", .Keyword_return), Keyword.init("linksection", .Keyword_linksection), - Keyword.init("stdcallcc", .Keyword_stdcallcc), Keyword.init("struct", .Keyword_struct), Keyword.init("suspend", .Keyword_suspend), Keyword.init("switch", .Keyword_switch), @@ -181,7 +179,6 @@ pub const Token = struct { Keyword_for, Keyword_if, Keyword_inline, - Keyword_nakedcc, Keyword_noalias, Keyword_noinline, Keyword_nosuspend, @@ -194,7 +191,6 @@ pub const Token = struct { Keyword_resume, Keyword_return, Keyword_linksection, - Keyword_stdcallcc, Keyword_struct, Keyword_suspend, Keyword_switch, @@ -306,7 +302,6 @@ pub const Token = struct { .Keyword_for => "for", .Keyword_if => "if", .Keyword_inline => "inline", - .Keyword_nakedcc => "nakedcc", .Keyword_noalias => "noalias", .Keyword_noinline => "noinline", .Keyword_nosuspend => "nosuspend", @@ -318,7 +313,6 @@ pub const Token = struct { .Keyword_resume => "resume", .Keyword_return => "return", .Keyword_linksection => "linksection", - .Keyword_stdcallcc => "stdcallcc", .Keyword_struct => "struct", .Keyword_suspend => "suspend", .Keyword_switch => "switch", diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 1c689e9f76..6bbb133bb1 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -4094,7 +4094,6 @@ fn transCreateNodeMacroFn(c: *Context, name: []const u8, ref: *ast.Node, proto_a .return_type = proto_alias.return_type, .var_args_token = null, .extern_export_inline_token = inline_tok, - .cc_token = null, .body_node = null, .lib_name = null, .align_expr = null, @@ -4753,7 +4752,6 @@ fn finishTransFnProto( .return_type = .{ .Explicit = return_type_node }, .var_args_token = null, // TODO this field is broken in the AST data model .extern_export_inline_token = extern_export_inline_tok, - .cc_token = null, .body_node = null, .lib_name = null, .align_expr = align_expr, @@ -5119,7 +5117,6 @@ fn transMacroFnDefine(c: *Context, it: *CTokenList.Iterator, source: []const u8, .return_type = .{ .Explicit = &type_of.base }, .doc_comments = null, .var_args_token = null, - .cc_token = null, .body_node = null, .lib_name = null, .align_expr = null, diff --git a/src/all_types.hpp b/src/all_types.hpp index aeffa440ab..61b6cbd74a 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -718,7 +718,6 @@ struct AstNodeFnProto { Buf doc_comments; FnInline fn_inline; - bool is_async; VisibMod visib_mod; bool auto_err_set; diff --git a/src/analyze.cpp b/src/analyze.cpp index 4c3103c48c..39f797a9ec 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1528,8 +1528,6 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { } CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto) { - if (fn_proto->is_async) - return CallingConventionAsync; // Compatible with the C ABI if (fn_proto->is_extern || fn_proto->is_export) return CallingConventionC; diff --git a/src/parser.cpp b/src/parser.cpp index 71f7adf7d1..1a929cd1b1 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -93,7 +93,6 @@ static AstNode *ast_parse_field_init(ParseContext *pc); static AstNode *ast_parse_while_continue_expr(ParseContext *pc); static AstNode *ast_parse_link_section(ParseContext *pc); static AstNode *ast_parse_callconv(ParseContext *pc); -static Optional ast_parse_fn_cc(ParseContext *pc); static AstNode *ast_parse_param_decl(ParseContext *pc); static AstNode *ast_parse_param_type(ParseContext *pc); static AstNode *ast_parse_if_prefix(ParseContext *pc); @@ -707,7 +706,6 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B fn_proto->column = first->start_column; fn_proto->data.fn_proto.visib_mod = visib_mod; fn_proto->data.fn_proto.doc_comments = *doc_comments; - // ast_parse_fn_cc may set it if (!fn_proto->data.fn_proto.is_extern) fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; @@ -788,29 +786,11 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, B return nullptr; } -// FnProto <- FnCC? KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) +// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) static AstNode *ast_parse_fn_proto(ParseContext *pc) { - Token *first = peek_token(pc); - AstNodeFnProto fn_cc; - Token *fn; - if (ast_parse_fn_cc(pc).unwrap(&fn_cc)) { - // The extern keyword for fn CC is also used for container decls. - // We therefore put it back, as allow container decl to consume it - // later. - if (fn_cc.is_extern) { - fn = eat_token_if(pc, TokenIdKeywordFn); - if (fn == nullptr) { - put_back_token(pc); - return nullptr; - } - } else { - fn = expect_token(pc, TokenIdKeywordFn); - } - } else { - fn_cc = {}; - fn = eat_token_if(pc, TokenIdKeywordFn); - if (fn == nullptr) - return nullptr; + Token *first = eat_token_if(pc, TokenIdKeywordFn); + if (first == nullptr) { + return nullptr; } Token *identifier = eat_token_if(pc, TokenIdSymbol); @@ -830,7 +810,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { } AstNode *res = ast_create_node(pc, NodeTypeFnProto, first); - res->data.fn_proto = fn_cc; + res->data.fn_proto = {}; res->data.fn_proto.name = token_buf(identifier); res->data.fn_proto.params = params; res->data.fn_proto.align_expr = align_expr; @@ -1524,17 +1504,6 @@ static AstNode *ast_parse_error_union_expr(ParseContext *pc) { static AstNode *ast_parse_suffix_expr(ParseContext *pc) { Token *async_token = eat_token_if(pc, TokenIdKeywordAsync); if (async_token) { - if (eat_token_if(pc, TokenIdKeywordFn) != nullptr) { - // HACK: If we see the keyword `fn`, then we assume that - // we are parsing an async fn proto, and not a call. - // We therefore put back all tokens consumed by the async - // prefix... - put_back_token(pc); - put_back_token(pc); - - return ast_parse_primary_type_expr(pc); - } - AstNode *child = ast_expect(pc, ast_parse_primary_type_expr); while (true) { AstNode *suffix = ast_parse_suffix_op(pc); @@ -2187,23 +2156,6 @@ static AstNode *ast_parse_callconv(ParseContext *pc) { return res; } -// FnCC -// <- KEYWORD_extern -// / KEYWORD_async -static Optional ast_parse_fn_cc(ParseContext *pc) { - AstNodeFnProto res = {}; - if (eat_token_if(pc, TokenIdKeywordAsync) != nullptr) { - res.is_async = true; - return Optional::some(res); - } - if (eat_token_if(pc, TokenIdKeywordExtern) != nullptr) { - res.is_extern = true; - return Optional::some(res); - } - - return Optional::none(); -} - // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType static AstNode *ast_parse_param_decl(ParseContext *pc) { Buf doc_comments = BUF_INIT; From d0e996405bff4352c78c570b4944b369d642d058 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Mon, 4 May 2020 09:24:46 -0600 Subject: [PATCH 17/74] add zig fmt fix for async/extern fn --- lib/std/zig/ast.zig | 2 ++ lib/std/zig/parse.zig | 32 +++++++++++++++++++++++++++- lib/std/zig/parser_test.zig | 42 +++++++++++++++++++++---------------- lib/std/zig/render.zig | 7 ++++++- 4 files changed, 63 insertions(+), 20 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 220b0390f1..8dec2de15c 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -880,6 +880,8 @@ pub const Node = struct { align_expr: ?*Node, // populated if align(A) is present section_expr: ?*Node, // populated if linksection(A) is present callconv_expr: ?*Node, // populated if callconv(A) is present + is_extern_prototype: bool = false, // TODO: Remove once extern fn rewriting is + is_async: bool = false, // TODO: remove once async fn rewriting is pub const ParamList = SegmentedList(*Node, 2); diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index ac1c1f8b15..031fd9c160 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -337,7 +337,25 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { - const fn_token = eatToken(it, .Keyword_fn) orelse return null; + // TODO: Remove once extern/async fn rewriting is + var is_async = false; + var is_extern = false; + const cc_token: ?usize = blk: { + if (eatToken(it, .Keyword_extern)) |token| { + is_extern = true; + break :blk token; + } + if (eatToken(it, .Keyword_async)) |token| { + is_async = true; + break :blk token; + } + break :blk null; + }; + const fn_token = eatToken(it, .Keyword_fn) orelse { + if (cc_token) |token| + putBackToken(it, token); + return null; + }; const name_token = eatToken(it, .Identifier); const lparen = try expectToken(it, tree, .LParen); const params = try parseParamDeclList(arena, it, tree); @@ -381,6 +399,8 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { .align_expr = align_expr, .section_expr = section_expr, .callconv_expr = callconv_expr, + .is_extern_prototype = is_extern, + .is_async = is_async, }; return &fn_proto_node.base; @@ -1175,6 +1195,16 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const maybe_async = eatToken(it, .Keyword_async); if (maybe_async) |async_token| { const token_fn = eatToken(it, .Keyword_fn); + if (token_fn != null) { + // TODO: remove this hack when async fn rewriting is + // HACK: If we see the keyword `fn`, then we assume that + // we are parsing an async fn proto, and not a call. + // We therefore put back all tokens consumed by the async + // prefix... + putBackToken(it, token_fn.?); + putBackToken(it, async_token); + return parsePrimaryTypeExpr(arena, it, tree); + } var res = try expectNode(arena, it, tree, parsePrimaryTypeExpr, .{ .ExpectedPrimaryTypeExpr = .{ .token = it.index }, }); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 198ce1ad94..7ab3e86b1a 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -236,10 +236,10 @@ test "zig fmt: anon list literal syntax" { test "zig fmt: async function" { try testCanonical( \\pub const Server = struct { - \\ handleRequestFn: async fn (*Server, *const std.net.Address, File) void, + \\ handleRequestFn: fn (*Server, *const std.net.Address, File) callconv(.Async) void, \\}; \\test "hi" { - \\ var ptr = @ptrCast(async fn (i32) void, other); + \\ var ptr = @ptrCast(fn (i32) callconv(.Async) void, other); \\} \\ ); @@ -435,15 +435,6 @@ test "zig fmt: aligned struct field" { ); } -test "zig fmt: preserve space between async fn definitions" { - try testCanonical( - \\async fn a() void {} - \\ - \\async fn b() void {} - \\ - ); -} - test "zig fmt: comment to disable/enable zig fmt first" { try testCanonical( \\// Test trailing comma syntax @@ -1499,7 +1490,7 @@ test "zig fmt: line comments in struct initializer" { test "zig fmt: first line comment in struct initializer" { try testCanonical( - \\pub async fn acquire(self: *Self) HeldLock { + \\pub fn acquire(self: *Self) HeldLock { \\ return HeldLock{ \\ // guaranteed allocation elision \\ .held = self.lock.acquire(), @@ -2461,8 +2452,7 @@ test "zig fmt: fn type" { \\} \\ \\const a: fn (u8) u8 = undefined; - \\const b: extern fn (u8) u8 = undefined; - \\const c: fn (u8) callconv(.Naked) u8 = undefined; + \\const b: fn (u8) callconv(.Naked) u8 = undefined; \\const ap: fn (u8) u8 = a; \\ ); @@ -2484,7 +2474,7 @@ test "zig fmt: inline asm" { test "zig fmt: async functions" { try testCanonical( - \\async fn simpleAsyncFn() void { + \\fn simpleAsyncFn() void { \\ const a = async a.b(); \\ x += 1; \\ suspend; @@ -2920,6 +2910,25 @@ test "zig fmt: noasync to nosuspend" { \\pub fn main() void { \\ nosuspend call(); \\} + ); +} + +test "zig fmt: convert async fn into callconv(.Async)" { + try testTransform( + \\async fn foo() void {} + , + \\fn foo() callconv(.Async) void {} + \\ + ); +} + +test "zig fmt: convert extern fn proto into callconv(.C)" { + try testTransform( + \\extern fn foo0() void {} + \\const foo1 = extern fn () void; + , + \\extern fn foo0() void {} + \\const foo1 = fn () callconv(.C) void; \\ ); } @@ -2970,7 +2979,6 @@ fn testParse(source: []const u8, allocator: *mem.Allocator, anything_changed: *b anything_changed.* = try std.zig.render(allocator, buffer.outStream(), tree); return buffer.toOwnedSlice(); } - fn testTransform(source: []const u8, expected_source: []const u8) !void { const needed_alloc_count = x: { // Try it once with unlimited memory, make sure it works @@ -3018,11 +3026,9 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { } } } - fn testCanonical(source: []const u8) !void { return testTransform(source, source); } - fn testError(source: []const u8) !void { const tree = try std.zig.parse(std.testing.allocator, source); defer tree.deinit(); diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 3e2cebcd8a..bcdc08d43a 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1414,7 +1414,8 @@ fn renderExpression( } if (fn_proto.extern_export_inline_token) |extern_export_inline_token| { - try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export + if (!fn_proto.is_extern_prototype) + try renderToken(tree, stream, extern_export_inline_token, indent, start_col, Space.Space); // extern/export/inline } if (fn_proto.lib_name) |lib_name| { @@ -1510,6 +1511,10 @@ fn renderExpression( try renderToken(tree, stream, callconv_lparen, indent, start_col, Space.None); // ( try renderExpression(allocator, stream, tree, indent, start_col, callconv_expr, Space.None); try renderToken(tree, stream, callconv_rparen, indent, start_col, Space.Space); // ) + } else if (fn_proto.is_extern_prototype) { + try stream.writeAll("callconv(.C) "); + } else if (fn_proto.is_async) { + try stream.writeAll("callconv(.Async) "); } switch (fn_proto.return_type) { From 6745a6f6f6f2b8d4473f00bed03a6cf1af117890 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Mon, 4 May 2020 09:49:27 -0600 Subject: [PATCH 18/74] zig fmt --- lib/std/c.zig | 2 +- lib/std/c/dragonfly.zig | 2 +- lib/std/c/freebsd.zig | 2 +- lib/std/c/linux.zig | 2 +- lib/std/c/netbsd.zig | 2 +- lib/std/event/channel.zig | 11 ++-- lib/std/event/future.zig | 4 +- lib/std/event/group.zig | 16 ++--- lib/std/event/lock.zig | 8 +-- lib/std/event/locked.zig | 2 +- lib/std/event/loop.zig | 2 +- lib/std/event/rwlock.zig | 13 ++-- lib/std/event/rwlocked.zig | 4 +- lib/std/os/bits/darwin.zig | 2 +- lib/std/os/bits/dragonfly.zig | 12 ++-- lib/std/os/bits/freebsd.zig | 10 +-- lib/std/os/bits/linux.zig | 10 +-- lib/std/os/linux.zig | 4 +- lib/std/os/linux/arm-eabi.zig | 2 +- lib/std/os/linux/arm64.zig | 2 +- lib/std/os/linux/i386.zig | 2 +- lib/std/os/linux/mips.zig | 2 +- lib/std/os/linux/riscv64.zig | 2 +- lib/std/os/linux/x86_64.zig | 2 +- .../protocols/absolute_pointer_protocol.zig | 4 +- .../uefi/protocols/edid_override_protocol.zig | 2 +- lib/std/os/uefi/protocols/file_protocol.zig | 20 +++--- .../protocols/graphics_output_protocol.zig | 6 +- .../uefi/protocols/hii_database_protocol.zig | 8 +-- .../os/uefi/protocols/hii_popup_protocol.zig | 2 +- .../os/uefi/protocols/ip6_config_protocol.zig | 8 +-- lib/std/os/uefi/protocols/ip6_protocol.zig | 18 +++--- .../ip6_service_binding_protocol.zig | 4 +- .../uefi/protocols/loaded_image_protocol.zig | 2 +- .../protocols/managed_network_protocol.zig | 16 ++--- ...naged_network_service_binding_protocol.zig | 4 +- lib/std/os/uefi/protocols/rng_protocol.zig | 4 +- .../protocols/simple_file_system_protocol.zig | 2 +- .../protocols/simple_network_protocol.zig | 26 ++++---- .../protocols/simple_pointer_protocol.zig | 4 +- .../simple_text_input_ex_protocol.zig | 12 ++-- .../protocols/simple_text_input_protocol.zig | 4 +- .../protocols/simple_text_output_protocol.zig | 18 +++--- lib/std/os/uefi/protocols/udp6_protocol.zig | 14 ++-- .../udp6_service_binding_protocol.zig | 4 +- lib/std/os/uefi/tables/boot_services.zig | 64 +++++++++---------- lib/std/os/uefi/tables/runtime_services.zig | 10 +-- lib/std/os/windows/bits.zig | 12 ++-- lib/std/os/windows/ws2_32.zig | 2 +- lib/std/special/test_runner.zig | 2 +- lib/std/start.zig | 3 +- src-self-hosted/clang.zig | 2 +- src-self-hosted/main.zig | 5 +- test/stage1/behavior/async_fn.zig | 54 ++++++++-------- test/stage1/behavior/await_struct.zig | 4 +- test/stage1/behavior/cast.zig | 2 +- 56 files changed, 222 insertions(+), 240 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 9f1114b9c1..0f166b7e59 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -217,7 +217,7 @@ pub extern "c" fn utimes(path: [*:0]const u8, times: *[2]timeval) c_int; pub extern "c" fn utimensat(dirfd: fd_t, pathname: [*:0]const u8, times: *[2]timespec, flags: u32) c_int; pub extern "c" fn futimens(fd: fd_t, times: *const [2]timespec) c_int; -pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const pthread_attr_t, start_routine: extern fn (?*c_void) ?*c_void, noalias arg: ?*c_void) c_int; +pub extern "c" fn pthread_create(noalias newthread: *pthread_t, noalias attr: ?*const pthread_attr_t, start_routine: fn (?*c_void) callconv(.C) ?*c_void, noalias arg: ?*c_void) c_int; pub extern "c" fn pthread_attr_init(attr: *pthread_attr_t) c_int; pub extern "c" fn pthread_attr_setstack(attr: *pthread_attr_t, stackaddr: *c_void, stacksize: usize) c_int; pub extern "c" fn pthread_attr_setguardsize(attr: *pthread_attr_t, guardsize: usize) c_int; diff --git a/lib/std/c/dragonfly.zig b/lib/std/c/dragonfly.zig index a271b2e869..0c859018be 100644 --- a/lib/std/c/dragonfly.zig +++ b/lib/std/c/dragonfly.zig @@ -9,7 +9,7 @@ pub extern "c" fn getdents(fd: c_int, buf_ptr: [*]u8, nbytes: usize) usize; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize; -pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; +pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; pub const pthread_mutex_t = extern struct { diff --git a/lib/std/c/freebsd.zig b/lib/std/c/freebsd.zig index 3a0634dbb7..ea52c05f0b 100644 --- a/lib/std/c/freebsd.zig +++ b/lib/std/c/freebsd.zig @@ -24,7 +24,7 @@ pub extern "c" fn sendfile( flags: u32, ) c_int; -pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; +pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; pub const pthread_mutex_t = extern struct { diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index 1da0db57d6..4ceeb5a773 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -75,7 +75,7 @@ pub extern "c" fn inotify_add_watch(fd: fd_t, pathname: [*]const u8, mask: u32) /// See std.elf for constants for this pub extern "c" fn getauxval(__type: c_ulong) c_ulong; -pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; +pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int; diff --git a/lib/std/c/netbsd.zig b/lib/std/c/netbsd.zig index 20960b3f77..31adbb1f59 100644 --- a/lib/std/c/netbsd.zig +++ b/lib/std/c/netbsd.zig @@ -6,7 +6,7 @@ usingnamespace std.c; extern "c" fn __errno() *c_int; pub const _errno = __errno; -pub const dl_iterate_phdr_callback = extern fn (info: *dl_phdr_info, size: usize, data: ?*c_void) c_int; +pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; pub extern "c" fn arc4random_buf(buf: [*]u8, len: usize) void; diff --git a/lib/std/event/channel.zig b/lib/std/event/channel.zig index 83c77bcac5..5aef0bb3ba 100644 --- a/lib/std/event/channel.zig +++ b/lib/std/event/channel.zig @@ -105,7 +105,7 @@ pub fn Channel(comptime T: type) type { /// await this function to get an item from the channel. If the buffer is empty, the frame will /// complete when the next item is put in the channel. - pub async fn get(self: *SelfChannel) T { + pub fn get(self: *SelfChannel) callconv(.Async) T { // TODO https://github.com/ziglang/zig/issues/2765 var result: T = undefined; var my_tick_node = Loop.NextTickNode.init(@frame()); @@ -305,8 +305,7 @@ test "std.event.Channel wraparound" { channel.put(7); testing.expectEqual(@as(i32, 7), channel.get()); } - -async fn testChannelGetter(channel: *Channel(i32)) void { +fn testChannelGetter(channel: *Channel(i32)) callconv(.Async) void { const value1 = channel.get(); testing.expect(value1 == 1234); @@ -321,12 +320,10 @@ async fn testChannelGetter(channel: *Channel(i32)) void { testing.expect(value4.? == 4444); await last_put; } - -async fn testChannelPutter(channel: *Channel(i32)) void { +fn testChannelPutter(channel: *Channel(i32)) callconv(.Async) void { channel.put(1234); channel.put(4567); } - -async fn testPut(channel: *Channel(i32), value: i32) void { +fn testPut(channel: *Channel(i32), value: i32) callconv(.Async) void { channel.put(value); } diff --git a/lib/std/event/future.zig b/lib/std/event/future.zig index 51a63e90ee..5de22c574c 100644 --- a/lib/std/event/future.zig +++ b/lib/std/event/future.zig @@ -34,7 +34,7 @@ pub fn Future(comptime T: type) type { /// Obtain the value. If it's not available, wait until it becomes /// available. /// Thread-safe. - pub async fn get(self: *Self) *T { + pub fn get(self: *Self) callconv(.Async) *T { if (@atomicLoad(Available, &self.available, .SeqCst) == .Finished) { return &self.data; } @@ -59,7 +59,7 @@ pub fn Future(comptime T: type) type { /// should start working on the data. /// It's not required to call start() before resolve() but it can be useful since /// this method is thread-safe. - pub async fn start(self: *Self) ?*T { + pub fn start(self: *Self) callconv(.Async) ?*T { const state = @cmpxchgStrong(Available, &self.available, .NotStarted, .Started, .SeqCst, .SeqCst) orelse return null; switch (state) { .Started => { diff --git a/lib/std/event/group.zig b/lib/std/event/group.zig index 5eebb7ffbc..155a9486b7 100644 --- a/lib/std/event/group.zig +++ b/lib/std/event/group.zig @@ -84,7 +84,7 @@ pub fn Group(comptime ReturnType: type) type { /// Wait for all the calls and promises of the group to complete. /// Thread-safe. /// Safe to call any number of times. - pub async fn wait(self: *Self) ReturnType { + pub fn wait(self: *Self) callconv(.Async) ReturnType { const held = self.lock.acquire(); defer held.release(); @@ -127,8 +127,7 @@ test "std.event.Group" { const handle = async testGroup(std.heap.page_allocator); } - -async fn testGroup(allocator: *Allocator) void { +fn testGroup(allocator: *Allocator) callconv(.Async) void { var count: usize = 0; var group = Group(void).init(allocator); var sleep_a_little_frame = async sleepALittle(&count); @@ -145,20 +144,17 @@ async fn testGroup(allocator: *Allocator) void { another.add(&something_that_fails_frame) catch @panic("memory"); testing.expectError(error.ItBroke, another.wait()); } - -async fn sleepALittle(count: *usize) void { +fn sleepALittle(count: *usize) callconv(.Async) void { std.time.sleep(1 * std.time.millisecond); _ = @atomicRmw(usize, count, .Add, 1, .SeqCst); } - -async fn increaseByTen(count: *usize) void { +fn increaseByTen(count: *usize) callconv(.Async) void { var i: usize = 0; while (i < 10) : (i += 1) { _ = @atomicRmw(usize, count, .Add, 1, .SeqCst); } } - -async fn doSomethingThatFails() anyerror!void {} -async fn somethingElse() anyerror!void { +fn doSomethingThatFails() callconv(.Async) anyerror!void {} +fn somethingElse() callconv(.Async) anyerror!void { return error.ItBroke; } diff --git a/lib/std/event/lock.zig b/lib/std/event/lock.zig index ff1f738c5e..179b881c9c 100644 --- a/lib/std/event/lock.zig +++ b/lib/std/event/lock.zig @@ -89,7 +89,7 @@ pub const Lock = struct { while (self.queue.get()) |node| resume node.data; } - pub async fn acquire(self: *Lock) Held { + pub fn acquire(self: *Lock) callconv(.Async) Held { var my_tick_node = Loop.NextTickNode.init(@frame()); errdefer _ = self.queue.remove(&my_tick_node); // TODO test canceling an acquire @@ -134,8 +134,7 @@ test "std.event.Lock" { const expected_result = [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; testing.expectEqualSlices(i32, &expected_result, &shared_test_data); } - -async fn testLock(lock: *Lock) void { +fn testLock(lock: *Lock) callconv(.Async) void { var handle1 = async lockRunner(lock); var tick_node1 = Loop.NextTickNode{ .prev = undefined, @@ -167,8 +166,7 @@ async fn testLock(lock: *Lock) void { var shared_test_data = [1]i32{0} ** 10; var shared_test_index: usize = 0; - -async fn lockRunner(lock: *Lock) void { +fn lockRunner(lock: *Lock) callconv(.Async) void { suspend; // resumed by onNextTick var i: usize = 0; diff --git a/lib/std/event/locked.zig b/lib/std/event/locked.zig index 5e9c0ea10e..e921803447 100644 --- a/lib/std/event/locked.zig +++ b/lib/std/event/locked.zig @@ -31,7 +31,7 @@ pub fn Locked(comptime T: type) type { self.lock.deinit(); } - pub async fn acquire(self: *Self) HeldLock { + pub fn acquire(self: *Self) callconv(.Async) HeldLock { return HeldLock{ // TODO guaranteed allocation elision .held = self.lock.acquire(), diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 15e7a3481c..e55d5116b9 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -503,7 +503,7 @@ pub const Loop = struct { } } - pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) void { + pub fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) callconv(.Async) void { var resume_node = ResumeNode.Basic{ .base = ResumeNode{ .id = ResumeNode.Id.Basic, diff --git a/lib/std/event/rwlock.zig b/lib/std/event/rwlock.zig index 425088063f..7a47c27dd8 100644 --- a/lib/std/event/rwlock.zig +++ b/lib/std/event/rwlock.zig @@ -97,7 +97,7 @@ pub const RwLock = struct { while (self.reader_queue.get()) |node| resume node.data; } - pub async fn acquireRead(self: *RwLock) HeldRead { + pub fn acquireRead(self: *RwLock) callconv(.Async) HeldRead { _ = @atomicRmw(usize, &self.reader_lock_count, .Add, 1, .SeqCst); suspend { @@ -130,7 +130,7 @@ pub const RwLock = struct { return HeldRead{ .lock = self }; } - pub async fn acquireWrite(self: *RwLock) HeldWrite { + pub fn acquireWrite(self: *RwLock) callconv(.Async) HeldWrite { suspend { var my_tick_node = Loop.NextTickNode{ .data = @frame(), @@ -225,8 +225,7 @@ test "std.event.RwLock" { const expected_result = [1]i32{shared_it_count * @intCast(i32, shared_test_data.len)} ** shared_test_data.len; testing.expectEqualSlices(i32, expected_result, shared_test_data); } - -async fn testLock(allocator: *Allocator, lock: *RwLock) void { +fn testLock(allocator: *Allocator, lock: *RwLock) callconv(.Async) void { var read_nodes: [100]Loop.NextTickNode = undefined; for (read_nodes) |*read_node| { const frame = allocator.create(@Frame(readRunner)) catch @panic("memory"); @@ -259,8 +258,7 @@ const shared_it_count = 10; var shared_test_data = [1]i32{0} ** 10; var shared_test_index: usize = 0; var shared_count: usize = 0; - -async fn writeRunner(lock: *RwLock) void { +fn writeRunner(lock: *RwLock) callconv(.Async) void { suspend; // resumed by onNextTick var i: usize = 0; @@ -277,8 +275,7 @@ async fn writeRunner(lock: *RwLock) void { shared_test_index = 0; } } - -async fn readRunner(lock: *RwLock) void { +fn readRunner(lock: *RwLock) callconv(.Async) void { suspend; // resumed by onNextTick std.time.sleep(1); diff --git a/lib/std/event/rwlocked.zig b/lib/std/event/rwlocked.zig index 3f4c6ddbf8..9a569e8f1f 100644 --- a/lib/std/event/rwlocked.zig +++ b/lib/std/event/rwlocked.zig @@ -40,14 +40,14 @@ pub fn RwLocked(comptime T: type) type { self.lock.deinit(); } - pub async fn acquireRead(self: *Self) HeldReadLock { + pub fn acquireRead(self: *Self) callconv(.Async) HeldReadLock { return HeldReadLock{ .held = self.lock.acquireRead(), .value = &self.locked_data, }; } - pub async fn acquireWrite(self: *Self) HeldWriteLock { + pub fn acquireWrite(self: *Self) callconv(.Async) HeldWriteLock { return HeldWriteLock{ .held = self.lock.acquireWrite(), .value = &self.locked_data, diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index d116d6157a..8a596331a6 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -125,7 +125,7 @@ pub const empty_sigset = sigset_t(0); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name. pub const Sigaction = extern struct { - handler: extern fn (c_int) void, + handler: fn (c_int) callconv(.C) void, sa_mask: sigset_t, sa_flags: c_int, }; diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 6a6c871fc5..df22678323 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -458,9 +458,9 @@ pub const S_IFSOCK = 49152; pub const S_IFWHT = 57344; pub const S_IFMT = 61440; -pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); -pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); -pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); +pub const SIG_ERR = @intToPtr(fn (i32) callconv(.C) void, maxInt(usize)); +pub const SIG_DFL = @intToPtr(fn (i32) callconv(.C) void, 0); +pub const SIG_IGN = @intToPtr(fn (i32) callconv(.C) void, 1); pub const BADSIG = SIG_ERR; pub const SIG_BLOCK = 1; pub const SIG_UNBLOCK = 2; @@ -519,13 +519,13 @@ pub const sigset_t = extern struct { pub const sig_atomic_t = c_int; pub const Sigaction = extern struct { __sigaction_u: extern union { - __sa_handler: ?extern fn (c_int) void, - __sa_sigaction: ?extern fn (c_int, [*c]siginfo_t, ?*c_void) void, + __sa_handler: ?fn (c_int) callconv(.C) void, + __sa_sigaction: ?fn (c_int, [*c]siginfo_t, ?*c_void) callconv(.C) void, }, sa_flags: c_int, sa_mask: sigset_t, }; -pub const sig_t = [*c]extern fn (c_int) void; +pub const sig_t = [*c]fn (c_int) callconv(.C) void; pub const sigvec = extern struct { sv_handler: [*c]__sighandler_t, diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index 9999dca62f..eee7504366 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -725,16 +725,16 @@ pub const winsize = extern struct { const NSIG = 32; -pub const SIG_ERR = @intToPtr(extern fn (i32) void, maxInt(usize)); -pub const SIG_DFL = @intToPtr(extern fn (i32) void, 0); -pub const SIG_IGN = @intToPtr(extern fn (i32) void, 1); +pub const SIG_ERR = @intToPtr(fn (i32) callconv(.C) void, maxInt(usize)); +pub const SIG_DFL = @intToPtr(fn (i32) callconv(.C) void, 0); +pub const SIG_IGN = @intToPtr(fn (i32) callconv(.C) void, 1); /// Renamed from `sigaction` to `Sigaction` to avoid conflict with the syscall. pub const Sigaction = extern struct { /// signal handler __sigaction_u: extern union { - __sa_handler: extern fn (i32) void, - __sa_sigaction: extern fn (i32, *__siginfo, usize) void, + __sa_handler: fn (i32) callconv(.C) void, + __sa_sigaction: fn (i32, *__siginfo, usize) callconv(.C) void, }, /// see signal options diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 750b487754..438be2299b 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -813,15 +813,15 @@ pub const app_mask: sigset_t = [2]u32{ 0xfffffffc, 0x7fffffff } ++ [_]u32{0xffff pub const k_sigaction = if (is_mips) extern struct { flags: usize, - sigaction: ?extern fn (i32, *siginfo_t, ?*c_void) void, + sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, mask: [4]u32, - restorer: extern fn () void, + restorer: fn () callconv(.C) void, } else extern struct { - sigaction: ?extern fn (i32, *siginfo_t, ?*c_void) void, + sigaction: ?fn (i32, *siginfo_t, ?*c_void) callconv(.C) void, flags: usize, - restorer: extern fn () void, + restorer: fn () callconv(.C) void, mask: [2]u32, }; @@ -831,7 +831,7 @@ pub const Sigaction = extern struct { sigaction: ?sigaction_fn, mask: sigset_t, flags: u32, - restorer: ?extern fn () void = null, + restorer: ?fn () callconv(.C) void = null, }; pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize)); diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 15f9bf9b62..6653293e59 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -599,7 +599,7 @@ pub fn flock(fd: fd_t, operation: i32) usize { var vdso_clock_gettime = @ptrCast(?*const c_void, init_vdso_clock_gettime); // We must follow the C calling convention when we call into the VDSO -const vdso_clock_gettime_ty = extern fn (i32, *timespec) usize; +const vdso_clock_gettime_ty = fn (i32, *timespec) callconv(.C) usize; pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { if (@hasDecl(@This(), "VDSO_CGT_SYM")) { @@ -791,7 +791,7 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti .sigaction = act.sigaction, .flags = act.flags | SA_RESTORER, .mask = undefined, - .restorer = @ptrCast(extern fn () void, restorer_fn), + .restorer = @ptrCast(fn () callconv(.C) void, restorer_fn), }; var ksa_old: k_sigaction = undefined; const ksa_mask_size = @sizeOf(@TypeOf(ksa_old.mask)); diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm-eabi.zig index c052aeab4e..352afeeb04 100644 --- a/lib/std/os/linux/arm-eabi.zig +++ b/lib/std/os/linux/arm-eabi.zig @@ -86,7 +86,7 @@ pub fn syscall6( } /// This matches the libc clone function. -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub fn restore() callconv(.Naked) void { return asm volatile ("svc #0" diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/arm64.zig index 52ab3656e0..49548522ec 100644 --- a/lib/std/os/linux/arm64.zig +++ b/lib/std/os/linux/arm64.zig @@ -86,7 +86,7 @@ pub fn syscall6( } /// This matches the libc clone function. -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub const restore = restore_rt; diff --git a/lib/std/os/linux/i386.zig b/lib/std/os/linux/i386.zig index 0342f0754e..a4fdf8a346 100644 --- a/lib/std/os/linux/i386.zig +++ b/lib/std/os/linux/i386.zig @@ -106,7 +106,7 @@ pub fn socketcall(call: usize, args: [*]usize) usize { } /// This matches the libc clone function. -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub fn restore() callconv(.Naked) void { return asm volatile ("int $0x80" diff --git a/lib/std/os/linux/mips.zig b/lib/std/os/linux/mips.zig index 87c55db9f6..5b5c1e1f34 100644 --- a/lib/std/os/linux/mips.zig +++ b/lib/std/os/linux/mips.zig @@ -142,7 +142,7 @@ pub fn syscall6( } /// This matches the libc clone function. -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub fn restore() callconv(.Naked) void { return asm volatile ("syscall" diff --git a/lib/std/os/linux/riscv64.zig b/lib/std/os/linux/riscv64.zig index 3832bfbcca..39cc13f5b6 100644 --- a/lib/std/os/linux/riscv64.zig +++ b/lib/std/os/linux/riscv64.zig @@ -85,7 +85,7 @@ pub fn syscall6( ); } -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub const restore = restore_rt; diff --git a/lib/std/os/linux/x86_64.zig b/lib/std/os/linux/x86_64.zig index b60dcd80e9..33d2b66670 100644 --- a/lib/std/os/linux/x86_64.zig +++ b/lib/std/os/linux/x86_64.zig @@ -86,7 +86,7 @@ pub fn syscall6( } /// This matches the libc clone function. -pub extern fn clone(func: extern fn (arg: usize) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; +pub extern fn clone(func: fn (arg: usize) callconv(.C) u8, stack: usize, flags: usize, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; pub const restore = restore_rt; diff --git a/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig b/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig index 1a46b9cf2c..a06a19c1a4 100644 --- a/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig +++ b/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig @@ -5,8 +5,8 @@ const Status = uefi.Status; /// Protocol for touchscreens pub const AbsolutePointerProtocol = extern struct { - _reset: extern fn (*const AbsolutePointerProtocol, bool) Status, - _get_state: extern fn (*const AbsolutePointerProtocol, *AbsolutePointerState) Status, + _reset: fn (*const AbsolutePointerProtocol, bool) callconv(.C) Status, + _get_state: fn (*const AbsolutePointerProtocol, *AbsolutePointerState) callconv(.C) Status, wait_for_input: Event, mode: *AbsolutePointerMode, diff --git a/lib/std/os/uefi/protocols/edid_override_protocol.zig b/lib/std/os/uefi/protocols/edid_override_protocol.zig index 2c37baa7a4..efe73982e9 100644 --- a/lib/std/os/uefi/protocols/edid_override_protocol.zig +++ b/lib/std/os/uefi/protocols/edid_override_protocol.zig @@ -5,7 +5,7 @@ const Status = uefi.Status; /// Override EDID information pub const EdidOverrideProtocol = extern struct { - _get_edid: extern fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) Status, + _get_edid: fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) callconv(.C) Status, /// Returns policy information and potentially a replacement EDID for the specified video output device. /// attributes must be align(4) diff --git a/lib/std/os/uefi/protocols/file_protocol.zig b/lib/std/os/uefi/protocols/file_protocol.zig index 4331d9a38c..eacd777008 100644 --- a/lib/std/os/uefi/protocols/file_protocol.zig +++ b/lib/std/os/uefi/protocols/file_protocol.zig @@ -5,16 +5,16 @@ const Status = uefi.Status; pub const FileProtocol = extern struct { revision: u64, - _open: extern fn (*const FileProtocol, **const FileProtocol, [*:0]const u16, u64, u64) Status, - _close: extern fn (*const FileProtocol) Status, - _delete: extern fn (*const FileProtocol) Status, - _read: extern fn (*const FileProtocol, *usize, [*]u8) Status, - _write: extern fn (*const FileProtocol, *usize, [*]const u8) Status, - _get_position: extern fn (*const FileProtocol, *u64) Status, - _set_position: extern fn (*const FileProtocol, *const u64) Status, - _get_info: extern fn (*const FileProtocol, *align(8) const Guid, *const usize, [*]u8) Status, - _set_info: extern fn (*const FileProtocol, *align(8) const Guid, usize, [*]const u8) Status, - _flush: extern fn (*const FileProtocol) Status, + _open: fn (*const FileProtocol, **const FileProtocol, [*:0]const u16, u64, u64) callconv(.C) Status, + _close: fn (*const FileProtocol) callconv(.C) Status, + _delete: fn (*const FileProtocol) callconv(.C) Status, + _read: fn (*const FileProtocol, *usize, [*]u8) callconv(.C) Status, + _write: fn (*const FileProtocol, *usize, [*]const u8) callconv(.C) Status, + _get_position: fn (*const FileProtocol, *u64) callconv(.C) Status, + _set_position: fn (*const FileProtocol, *const u64) callconv(.C) Status, + _get_info: fn (*const FileProtocol, *align(8) const Guid, *const usize, [*]u8) callconv(.C) Status, + _set_info: fn (*const FileProtocol, *align(8) const Guid, usize, [*]const u8) callconv(.C) Status, + _flush: fn (*const FileProtocol) callconv(.C) Status, pub fn open(self: *const FileProtocol, new_handle: **const FileProtocol, file_name: [*:0]const u16, open_mode: u64, attributes: u64) Status { return self._open(self, new_handle, file_name, open_mode, attributes); diff --git a/lib/std/os/uefi/protocols/graphics_output_protocol.zig b/lib/std/os/uefi/protocols/graphics_output_protocol.zig index 7370f537bf..1ceccce0bf 100644 --- a/lib/std/os/uefi/protocols/graphics_output_protocol.zig +++ b/lib/std/os/uefi/protocols/graphics_output_protocol.zig @@ -4,9 +4,9 @@ const Status = uefi.Status; /// Graphics output pub const GraphicsOutputProtocol = extern struct { - _query_mode: extern fn (*const GraphicsOutputProtocol, u32, *usize, **GraphicsOutputModeInformation) Status, - _set_mode: extern fn (*const GraphicsOutputProtocol, u32) Status, - _blt: extern fn (*const GraphicsOutputProtocol, ?[*]GraphicsOutputBltPixel, GraphicsOutputBltOperation, usize, usize, usize, usize, usize, usize, usize) Status, + _query_mode: fn (*const GraphicsOutputProtocol, u32, *usize, **GraphicsOutputModeInformation) callconv(.C) Status, + _set_mode: fn (*const GraphicsOutputProtocol, u32) callconv(.C) Status, + _blt: fn (*const GraphicsOutputProtocol, ?[*]GraphicsOutputBltPixel, GraphicsOutputBltOperation, usize, usize, usize, usize, usize, usize, usize) callconv(.C) Status, mode: *GraphicsOutputProtocolMode, /// Returns information for an available graphics mode that the graphics device and the set of active video output devices supports. diff --git a/lib/std/os/uefi/protocols/hii_database_protocol.zig b/lib/std/os/uefi/protocols/hii_database_protocol.zig index c79f693f6f..e34f72c2f3 100644 --- a/lib/std/os/uefi/protocols/hii_database_protocol.zig +++ b/lib/std/os/uefi/protocols/hii_database_protocol.zig @@ -6,10 +6,10 @@ const hii = uefi.protocols.hii; /// Database manager for HII-related data structures. pub const HIIDatabaseProtocol = extern struct { _new_package_list: Status, // TODO - _remove_package_list: extern fn (*const HIIDatabaseProtocol, hii.HIIHandle) Status, - _update_package_list: extern fn (*const HIIDatabaseProtocol, hii.HIIHandle, *const hii.HIIPackageList) Status, - _list_package_lists: extern fn (*const HIIDatabaseProtocol, u8, ?*const Guid, *usize, [*]hii.HIIHandle) Status, - _export_package_lists: extern fn (*const HIIDatabaseProtocol, ?hii.HIIHandle, *usize, *hii.HIIPackageList) Status, + _remove_package_list: fn (*const HIIDatabaseProtocol, hii.HIIHandle) callconv(.C) Status, + _update_package_list: fn (*const HIIDatabaseProtocol, hii.HIIHandle, *const hii.HIIPackageList) callconv(.C) Status, + _list_package_lists: fn (*const HIIDatabaseProtocol, u8, ?*const Guid, *usize, [*]hii.HIIHandle) callconv(.C) Status, + _export_package_lists: fn (*const HIIDatabaseProtocol, ?hii.HIIHandle, *usize, *hii.HIIPackageList) callconv(.C) Status, _register_package_notify: Status, // TODO _unregister_package_notify: Status, // TODO _find_keyboard_layouts: Status, // TODO diff --git a/lib/std/os/uefi/protocols/hii_popup_protocol.zig b/lib/std/os/uefi/protocols/hii_popup_protocol.zig index 96afe21fbc..2e4f621b41 100644 --- a/lib/std/os/uefi/protocols/hii_popup_protocol.zig +++ b/lib/std/os/uefi/protocols/hii_popup_protocol.zig @@ -6,7 +6,7 @@ const hii = uefi.protocols.hii; /// Display a popup window pub const HIIPopupProtocol = extern struct { revision: u64, - _create_popup: extern fn (*const HIIPopupProtocol, HIIPopupStyle, HIIPopupType, hii.HIIHandle, u16, ?*HIIPopupSelection) Status, + _create_popup: fn (*const HIIPopupProtocol, HIIPopupStyle, HIIPopupType, hii.HIIHandle, u16, ?*HIIPopupSelection) callconv(.C) Status, /// Displays a popup window. pub fn createPopup(self: *const HIIPopupProtocol, style: HIIPopupStyle, popup_type: HIIPopupType, handle: hii.HIIHandle, msg: u16, user_selection: ?*HIIPopupSelection) Status { diff --git a/lib/std/os/uefi/protocols/ip6_config_protocol.zig b/lib/std/os/uefi/protocols/ip6_config_protocol.zig index 89ff39e8d1..99ba76aa17 100644 --- a/lib/std/os/uefi/protocols/ip6_config_protocol.zig +++ b/lib/std/os/uefi/protocols/ip6_config_protocol.zig @@ -4,10 +4,10 @@ const Event = uefi.Event; const Status = uefi.Status; pub const Ip6ConfigProtocol = extern struct { - _set_data: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, usize, *const c_void) Status, - _get_data: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, *usize, ?*const c_void) Status, - _register_data_notify: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) Status, - _unregister_data_notify: extern fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) Status, + _set_data: fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, usize, *const c_void) callconv(.C) Status, + _get_data: fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, *usize, ?*const c_void) callconv(.C) Status, + _register_data_notify: fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) callconv(.C) Status, + _unregister_data_notify: fn (*const Ip6ConfigProtocol, Ip6ConfigDataType, Event) callconv(.C) Status, pub fn setData(self: *const Ip6ConfigProtocol, data_type: Ip6ConfigDataType, data_size: usize, data: *const c_void) Status { return self._set_data(self, data_type, data_size, data); diff --git a/lib/std/os/uefi/protocols/ip6_protocol.zig b/lib/std/os/uefi/protocols/ip6_protocol.zig index f9a5c23d3c..b39ae60b2a 100644 --- a/lib/std/os/uefi/protocols/ip6_protocol.zig +++ b/lib/std/os/uefi/protocols/ip6_protocol.zig @@ -7,15 +7,15 @@ const ManagedNetworkConfigData = uefi.protocols.ManagedNetworkConfigData; const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; pub const Ip6Protocol = extern struct { - _get_mode_data: extern fn (*const Ip6Protocol, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) Status, - _configure: extern fn (*const Ip6Protocol, ?*const Ip6ConfigData) Status, - _groups: extern fn (*const Ip6Protocol, bool, ?*const Ip6Address) Status, - _routes: extern fn (*const Ip6Protocol, bool, ?*const Ip6Address, u8, ?*const Ip6Address) Status, - _neighbors: extern fn (*const Ip6Protocol, bool, *const Ip6Address, ?*const MacAddress, u32, bool) Status, - _transmit: extern fn (*const Ip6Protocol, *Ip6CompletionToken) Status, - _receive: extern fn (*const Ip6Protocol, *Ip6CompletionToken) Status, - _cancel: extern fn (*const Ip6Protocol, ?*Ip6CompletionToken) Status, - _poll: extern fn (*const Ip6Protocol) Status, + _get_mode_data: fn (*const Ip6Protocol, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) callconv(.C) Status, + _configure: fn (*const Ip6Protocol, ?*const Ip6ConfigData) callconv(.C) Status, + _groups: fn (*const Ip6Protocol, bool, ?*const Ip6Address) callconv(.C) Status, + _routes: fn (*const Ip6Protocol, bool, ?*const Ip6Address, u8, ?*const Ip6Address) callconv(.C) Status, + _neighbors: fn (*const Ip6Protocol, bool, *const Ip6Address, ?*const MacAddress, u32, bool) callconv(.C) Status, + _transmit: fn (*const Ip6Protocol, *Ip6CompletionToken) callconv(.C) Status, + _receive: fn (*const Ip6Protocol, *Ip6CompletionToken) callconv(.C) Status, + _cancel: fn (*const Ip6Protocol, ?*Ip6CompletionToken) callconv(.C) Status, + _poll: fn (*const Ip6Protocol) callconv(.C) Status, /// Gets the current operational settings for this instance of the EFI IPv6 Protocol driver. pub fn getModeData(self: *const Ip6Protocol, ip6_mode_data: ?*Ip6ModeData, mnp_config_data: ?*ManagedNetworkConfigData, snp_mode_data: ?*SimpleNetworkMode) Status { diff --git a/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig b/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig index 030ae5cae2..97ab1a431c 100644 --- a/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig +++ b/lib/std/os/uefi/protocols/ip6_service_binding_protocol.zig @@ -4,8 +4,8 @@ const Guid = uefi.Guid; const Status = uefi.Status; pub const Ip6ServiceBindingProtocol = extern struct { - _create_child: extern fn (*const Ip6ServiceBindingProtocol, *?Handle) Status, - _destroy_child: extern fn (*const Ip6ServiceBindingProtocol, Handle) Status, + _create_child: fn (*const Ip6ServiceBindingProtocol, *?Handle) callconv(.C) Status, + _destroy_child: fn (*const Ip6ServiceBindingProtocol, Handle) callconv(.C) Status, pub fn createChild(self: *const Ip6ServiceBindingProtocol, handle: *?Handle) Status { return self._create_child(self, handle); diff --git a/lib/std/os/uefi/protocols/loaded_image_protocol.zig b/lib/std/os/uefi/protocols/loaded_image_protocol.zig index cff2bdccc0..b8afcb1063 100644 --- a/lib/std/os/uefi/protocols/loaded_image_protocol.zig +++ b/lib/std/os/uefi/protocols/loaded_image_protocol.zig @@ -19,7 +19,7 @@ pub const LoadedImageProtocol = extern struct { image_size: u64, image_code_type: MemoryType, image_data_type: MemoryType, - _unload: extern fn (*const LoadedImageProtocol, Handle) Status, + _unload: fn (*const LoadedImageProtocol, Handle) callconv(.C) Status, /// Unloads an image from memory. pub fn unload(self: *const LoadedImageProtocol, handle: Handle) Status { diff --git a/lib/std/os/uefi/protocols/managed_network_protocol.zig b/lib/std/os/uefi/protocols/managed_network_protocol.zig index 60dc6996ad..34ef6c40fa 100644 --- a/lib/std/os/uefi/protocols/managed_network_protocol.zig +++ b/lib/std/os/uefi/protocols/managed_network_protocol.zig @@ -7,14 +7,14 @@ const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; const MacAddress = uefi.protocols.MacAddress; pub const ManagedNetworkProtocol = extern struct { - _get_mode_data: extern fn (*const ManagedNetworkProtocol, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) Status, - _configure: extern fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkConfigData) Status, - _mcast_ip_to_mac: extern fn (*const ManagedNetworkProtocol, bool, *const c_void, *MacAddress) Status, - _groups: extern fn (*const ManagedNetworkProtocol, bool, ?*const MacAddress) Status, - _transmit: extern fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) Status, - _receive: extern fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) Status, - _cancel: extern fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkCompletionToken) Status, - _poll: extern fn (*const ManagedNetworkProtocol) usize, + _get_mode_data: fn (*const ManagedNetworkProtocol, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) callconv(.C) Status, + _configure: fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkConfigData) callconv(.C) Status, + _mcast_ip_to_mac: fn (*const ManagedNetworkProtocol, bool, *const c_void, *MacAddress) callconv(.C) Status, + _groups: fn (*const ManagedNetworkProtocol, bool, ?*const MacAddress) callconv(.C) Status, + _transmit: fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) callconv(.C) Status, + _receive: fn (*const ManagedNetworkProtocol, *const ManagedNetworkCompletionToken) callconv(.C) Status, + _cancel: fn (*const ManagedNetworkProtocol, ?*const ManagedNetworkCompletionToken) callconv(.C) Status, + _poll: fn (*const ManagedNetworkProtocol) callconv(.C) usize, /// Returns the operational parameters for the current MNP child driver. /// May also support returning the underlying SNP driver mode data. diff --git a/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig b/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig index ea8bd470c3..e9657e4456 100644 --- a/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig +++ b/lib/std/os/uefi/protocols/managed_network_service_binding_protocol.zig @@ -4,8 +4,8 @@ const Guid = uefi.Guid; const Status = uefi.Status; pub const ManagedNetworkServiceBindingProtocol = extern struct { - _create_child: extern fn (*const ManagedNetworkServiceBindingProtocol, *?Handle) Status, - _destroy_child: extern fn (*const ManagedNetworkServiceBindingProtocol, Handle) Status, + _create_child: fn (*const ManagedNetworkServiceBindingProtocol, *?Handle) callconv(.C) Status, + _destroy_child: fn (*const ManagedNetworkServiceBindingProtocol, Handle) callconv(.C) Status, pub fn createChild(self: *const ManagedNetworkServiceBindingProtocol, handle: *?Handle) Status { return self._create_child(self, handle); diff --git a/lib/std/os/uefi/protocols/rng_protocol.zig b/lib/std/os/uefi/protocols/rng_protocol.zig index 4d5dd496af..a32b202f44 100644 --- a/lib/std/os/uefi/protocols/rng_protocol.zig +++ b/lib/std/os/uefi/protocols/rng_protocol.zig @@ -4,8 +4,8 @@ const Status = uefi.Status; /// Random Number Generator protocol pub const RNGProtocol = extern struct { - _get_info: extern fn (*const RNGProtocol, *usize, [*]align(8) Guid) Status, - _get_rng: extern fn (*const RNGProtocol, ?*align(8) const Guid, usize, [*]u8) Status, + _get_info: fn (*const RNGProtocol, *usize, [*]align(8) Guid) callconv(.C) Status, + _get_rng: fn (*const RNGProtocol, ?*align(8) const Guid, usize, [*]u8) callconv(.C) Status, /// Returns information about the random number generation implementation. pub fn getInfo(self: *const RNGProtocol, list_size: *usize, list: [*]align(8) Guid) Status { diff --git a/lib/std/os/uefi/protocols/simple_file_system_protocol.zig b/lib/std/os/uefi/protocols/simple_file_system_protocol.zig index 31da02595a..119c1e6587 100644 --- a/lib/std/os/uefi/protocols/simple_file_system_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_file_system_protocol.zig @@ -5,7 +5,7 @@ const Status = uefi.Status; pub const SimpleFileSystemProtocol = extern struct { revision: u64, - _open_volume: extern fn (*const SimpleFileSystemProtocol, **const FileProtocol) Status, + _open_volume: fn (*const SimpleFileSystemProtocol, **const FileProtocol) callconv(.C) Status, pub fn openVolume(self: *const SimpleFileSystemProtocol, root: **const FileProtocol) Status { return self._open_volume(self, root); diff --git a/lib/std/os/uefi/protocols/simple_network_protocol.zig b/lib/std/os/uefi/protocols/simple_network_protocol.zig index a0d85b06d1..ac7446036e 100644 --- a/lib/std/os/uefi/protocols/simple_network_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_network_protocol.zig @@ -5,19 +5,19 @@ const Status = uefi.Status; pub const SimpleNetworkProtocol = extern struct { revision: u64, - _start: extern fn (*const SimpleNetworkProtocol) Status, - _stop: extern fn (*const SimpleNetworkProtocol) Status, - _initialize: extern fn (*const SimpleNetworkProtocol, usize, usize) Status, - _reset: extern fn (*const SimpleNetworkProtocol, bool) Status, - _shutdown: extern fn (*const SimpleNetworkProtocol) Status, - _receive_filters: extern fn (*const SimpleNetworkProtocol, SimpleNetworkReceiveFilter, SimpleNetworkReceiveFilter, bool, usize, ?[*]const MacAddress) Status, - _station_address: extern fn (*const SimpleNetworkProtocol, bool, ?*const MacAddress) Status, - _statistics: extern fn (*const SimpleNetworkProtocol, bool, ?*usize, ?*NetworkStatistics) Status, - _mcast_ip_to_mac: extern fn (*const SimpleNetworkProtocol, bool, *const c_void, *MacAddress) Status, - _nvdata: extern fn (*const SimpleNetworkProtocol, bool, usize, usize, [*]u8) Status, - _get_status: extern fn (*const SimpleNetworkProtocol, *SimpleNetworkInterruptStatus, ?*?[*]u8) Status, - _transmit: extern fn (*const SimpleNetworkProtocol, usize, usize, [*]const u8, ?*const MacAddress, ?*const MacAddress, ?*const u16) Status, - _receive: extern fn (*const SimpleNetworkProtocol, ?*usize, *usize, [*]u8, ?*MacAddress, ?*MacAddress, ?*u16) Status, + _start: fn (*const SimpleNetworkProtocol) callconv(.C) Status, + _stop: fn (*const SimpleNetworkProtocol) callconv(.C) Status, + _initialize: fn (*const SimpleNetworkProtocol, usize, usize) callconv(.C) Status, + _reset: fn (*const SimpleNetworkProtocol, bool) callconv(.C) Status, + _shutdown: fn (*const SimpleNetworkProtocol) callconv(.C) Status, + _receive_filters: fn (*const SimpleNetworkProtocol, SimpleNetworkReceiveFilter, SimpleNetworkReceiveFilter, bool, usize, ?[*]const MacAddress) callconv(.C) Status, + _station_address: fn (*const SimpleNetworkProtocol, bool, ?*const MacAddress) callconv(.C) Status, + _statistics: fn (*const SimpleNetworkProtocol, bool, ?*usize, ?*NetworkStatistics) callconv(.C) Status, + _mcast_ip_to_mac: fn (*const SimpleNetworkProtocol, bool, *const c_void, *MacAddress) callconv(.C) Status, + _nvdata: fn (*const SimpleNetworkProtocol, bool, usize, usize, [*]u8) callconv(.C) Status, + _get_status: fn (*const SimpleNetworkProtocol, *SimpleNetworkInterruptStatus, ?*?[*]u8) callconv(.C) Status, + _transmit: fn (*const SimpleNetworkProtocol, usize, usize, [*]const u8, ?*const MacAddress, ?*const MacAddress, ?*const u16) callconv(.C) Status, + _receive: fn (*const SimpleNetworkProtocol, ?*usize, *usize, [*]u8, ?*MacAddress, ?*MacAddress, ?*u16) callconv(.C) Status, wait_for_packet: Event, mode: *SimpleNetworkMode, diff --git a/lib/std/os/uefi/protocols/simple_pointer_protocol.zig b/lib/std/os/uefi/protocols/simple_pointer_protocol.zig index 2d1c7d4504..d217ab5930 100644 --- a/lib/std/os/uefi/protocols/simple_pointer_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_pointer_protocol.zig @@ -5,8 +5,8 @@ const Status = uefi.Status; /// Protocol for mice pub const SimplePointerProtocol = struct { - _reset: extern fn (*const SimplePointerProtocol, bool) Status, - _get_state: extern fn (*const SimplePointerProtocol, *SimplePointerState) Status, + _reset: fn (*const SimplePointerProtocol, bool) callconv(.C) Status, + _get_state: fn (*const SimplePointerProtocol, *SimplePointerState) callconv(.C) Status, wait_for_input: Event, mode: *SimplePointerMode, diff --git a/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig index c361ffa9a1..4a2b098e61 100644 --- a/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig @@ -5,12 +5,12 @@ const Status = uefi.Status; /// Character input devices, e.g. Keyboard pub const SimpleTextInputExProtocol = extern struct { - _reset: extern fn (*const SimpleTextInputExProtocol, bool) Status, - _read_key_stroke_ex: extern fn (*const SimpleTextInputExProtocol, *KeyData) Status, + _reset: fn (*const SimpleTextInputExProtocol, bool) callconv(.C) Status, + _read_key_stroke_ex: fn (*const SimpleTextInputExProtocol, *KeyData) callconv(.C) Status, wait_for_key_ex: Event, - _set_state: extern fn (*const SimpleTextInputExProtocol, *const u8) Status, - _register_key_notify: extern fn (*const SimpleTextInputExProtocol, *const KeyData, extern fn (*const KeyData) usize, **c_void) Status, - _unregister_key_notify: extern fn (*const SimpleTextInputExProtocol, *const c_void) Status, + _set_state: fn (*const SimpleTextInputExProtocol, *const u8) callconv(.C) Status, + _register_key_notify: fn (*const SimpleTextInputExProtocol, *const KeyData, fn (*const KeyData) callconv(.C) usize, **c_void) callconv(.C) Status, + _unregister_key_notify: fn (*const SimpleTextInputExProtocol, *const c_void) callconv(.C) Status, /// Resets the input device hardware. pub fn reset(self: *const SimpleTextInputExProtocol, verify: bool) Status { @@ -28,7 +28,7 @@ pub const SimpleTextInputExProtocol = extern struct { } /// Register a notification function for a particular keystroke for the input device. - pub fn registerKeyNotify(self: *const SimpleTextInputExProtocol, key_data: *const KeyData, notify: extern fn (*const KeyData) usize, handle: **c_void) Status { + pub fn registerKeyNotify(self: *const SimpleTextInputExProtocol, key_data: *const KeyData, notify: fn (*const KeyData) callconv(.C) usize, handle: **c_void) Status { return self._register_key_notify(self, key_data, notify, handle); } diff --git a/lib/std/os/uefi/protocols/simple_text_input_protocol.zig b/lib/std/os/uefi/protocols/simple_text_input_protocol.zig index fdae001145..58ed071331 100644 --- a/lib/std/os/uefi/protocols/simple_text_input_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_text_input_protocol.zig @@ -6,8 +6,8 @@ const Status = uefi.Status; /// Character input devices, e.g. Keyboard pub const SimpleTextInputProtocol = extern struct { - _reset: extern fn (*const SimpleTextInputProtocol, bool) usize, - _read_key_stroke: extern fn (*const SimpleTextInputProtocol, *InputKey) Status, + _reset: fn (*const SimpleTextInputProtocol, bool) callconv(.C) usize, + _read_key_stroke: fn (*const SimpleTextInputProtocol, *InputKey) callconv(.C) Status, wait_for_key: Event, /// Resets the input device hardware. diff --git a/lib/std/os/uefi/protocols/simple_text_output_protocol.zig b/lib/std/os/uefi/protocols/simple_text_output_protocol.zig index 09f3cb1cd2..84f540cb78 100644 --- a/lib/std/os/uefi/protocols/simple_text_output_protocol.zig +++ b/lib/std/os/uefi/protocols/simple_text_output_protocol.zig @@ -4,15 +4,15 @@ const Status = uefi.Status; /// Character output devices pub const SimpleTextOutputProtocol = extern struct { - _reset: extern fn (*const SimpleTextOutputProtocol, bool) Status, - _output_string: extern fn (*const SimpleTextOutputProtocol, [*:0]const u16) Status, - _test_string: extern fn (*const SimpleTextOutputProtocol, [*:0]const u16) Status, - _query_mode: extern fn (*const SimpleTextOutputProtocol, usize, *usize, *usize) Status, - _set_mode: extern fn (*const SimpleTextOutputProtocol, usize) Status, - _set_attribute: extern fn (*const SimpleTextOutputProtocol, usize) Status, - _clear_screen: extern fn (*const SimpleTextOutputProtocol) Status, - _set_cursor_position: extern fn (*const SimpleTextOutputProtocol, usize, usize) Status, - _enable_cursor: extern fn (*const SimpleTextOutputProtocol, bool) Status, + _reset: fn (*const SimpleTextOutputProtocol, bool) callconv(.C) Status, + _output_string: fn (*const SimpleTextOutputProtocol, [*:0]const u16) callconv(.C) Status, + _test_string: fn (*const SimpleTextOutputProtocol, [*:0]const u16) callconv(.C) Status, + _query_mode: fn (*const SimpleTextOutputProtocol, usize, *usize, *usize) callconv(.C) Status, + _set_mode: fn (*const SimpleTextOutputProtocol, usize) callconv(.C) Status, + _set_attribute: fn (*const SimpleTextOutputProtocol, usize) callconv(.C) Status, + _clear_screen: fn (*const SimpleTextOutputProtocol) callconv(.C) Status, + _set_cursor_position: fn (*const SimpleTextOutputProtocol, usize, usize) callconv(.C) Status, + _enable_cursor: fn (*const SimpleTextOutputProtocol, bool) callconv(.C) Status, mode: *SimpleTextOutputMode, /// Resets the text output device hardware. diff --git a/lib/std/os/uefi/protocols/udp6_protocol.zig b/lib/std/os/uefi/protocols/udp6_protocol.zig index f0ab2789f3..46c76beaa6 100644 --- a/lib/std/os/uefi/protocols/udp6_protocol.zig +++ b/lib/std/os/uefi/protocols/udp6_protocol.zig @@ -9,13 +9,13 @@ const ManagedNetworkConfigData = uefi.protocols.ManagedNetworkConfigData; const SimpleNetworkMode = uefi.protocols.SimpleNetworkMode; pub const Udp6Protocol = extern struct { - _get_mode_data: extern fn (*const Udp6Protocol, ?*Udp6ConfigData, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) Status, - _configure: extern fn (*const Udp6Protocol, ?*const Udp6ConfigData) Status, - _groups: extern fn (*const Udp6Protocol, bool, ?*const Ip6Address) Status, - _transmit: extern fn (*const Udp6Protocol, *Udp6CompletionToken) Status, - _receive: extern fn (*const Udp6Protocol, *Udp6CompletionToken) Status, - _cancel: extern fn (*const Udp6Protocol, ?*Udp6CompletionToken) Status, - _poll: extern fn (*const Udp6Protocol) Status, + _get_mode_data: fn (*const Udp6Protocol, ?*Udp6ConfigData, ?*Ip6ModeData, ?*ManagedNetworkConfigData, ?*SimpleNetworkMode) callconv(.C) Status, + _configure: fn (*const Udp6Protocol, ?*const Udp6ConfigData) callconv(.C) Status, + _groups: fn (*const Udp6Protocol, bool, ?*const Ip6Address) callconv(.C) Status, + _transmit: fn (*const Udp6Protocol, *Udp6CompletionToken) callconv(.C) Status, + _receive: fn (*const Udp6Protocol, *Udp6CompletionToken) callconv(.C) Status, + _cancel: fn (*const Udp6Protocol, ?*Udp6CompletionToken) callconv(.C) Status, + _poll: fn (*const Udp6Protocol) callconv(.C) Status, pub fn getModeData(self: *const Udp6Protocol, udp6_config_data: ?*Udp6ConfigData, ip6_mode_data: ?*Ip6ModeData, mnp_config_data: ?*ManagedNetworkConfigData, snp_mode_data: ?*SimpleNetworkMode) Status { return self._get_mode_data(self, udp6_config_data, ip6_mode_data, mnp_config_data, snp_mode_data); diff --git a/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig b/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig index 9a7a67807c..811692adc3 100644 --- a/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig +++ b/lib/std/os/uefi/protocols/udp6_service_binding_protocol.zig @@ -4,8 +4,8 @@ const Guid = uefi.Guid; const Status = uefi.Status; pub const Udp6ServiceBindingProtocol = extern struct { - _create_child: extern fn (*const Udp6ServiceBindingProtocol, *?Handle) Status, - _destroy_child: extern fn (*const Udp6ServiceBindingProtocol, Handle) Status, + _create_child: fn (*const Udp6ServiceBindingProtocol, *?Handle) callconv(.C) Status, + _destroy_child: fn (*const Udp6ServiceBindingProtocol, Handle) callconv(.C) Status, pub fn createChild(self: *const Udp6ServiceBindingProtocol, handle: *?Handle) Status { return self._create_child(self, handle); diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig index 1969b46403..a1d2c1ca59 100644 --- a/lib/std/os/uefi/tables/boot_services.zig +++ b/lib/std/os/uefi/tables/boot_services.zig @@ -21,117 +21,117 @@ pub const BootServices = extern struct { hdr: TableHeader, /// Raises a task's priority level and returns its previous level. - raiseTpl: extern fn (usize) usize, + raiseTpl: fn (usize) callconv(.C) usize, /// Restores a task's priority level to its previous value. - restoreTpl: extern fn (usize) void, + restoreTpl: fn (usize) callconv(.C) void, /// Allocates memory pages from the system. - allocatePages: extern fn (AllocateType, MemoryType, usize, *[*]align(4096) u8) Status, + allocatePages: fn (AllocateType, MemoryType, usize, *[*]align(4096) u8) callconv(.C) Status, /// Frees memory pages. - freePages: extern fn ([*]align(4096) u8, usize) Status, + freePages: fn ([*]align(4096) u8, usize) callconv(.C) Status, /// Returns the current memory map. - getMemoryMap: extern fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) Status, + getMemoryMap: fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) callconv(.C) Status, /// Allocates pool memory. - allocatePool: extern fn (MemoryType, usize, *[*]align(8) u8) Status, + allocatePool: fn (MemoryType, usize, *[*]align(8) u8) callconv(.C) Status, /// Returns pool memory to the system. - freePool: extern fn ([*]align(8) u8) Status, + freePool: fn ([*]align(8) u8) callconv(.C) Status, /// Creates an event. - createEvent: extern fn (u32, usize, ?extern fn (Event, ?*c_void) void, ?*const c_void, *Event) Status, + createEvent: fn (u32, usize, ?fn (Event, ?*c_void) callconv(.C) void, ?*const c_void, *Event) callconv(.C) Status, /// Sets the type of timer and the trigger time for a timer event. - setTimer: extern fn (Event, TimerDelay, u64) Status, + setTimer: fn (Event, TimerDelay, u64) callconv(.C) Status, /// Stops execution until an event is signaled. - waitForEvent: extern fn (usize, [*]const Event, *usize) Status, + waitForEvent: fn (usize, [*]const Event, *usize) callconv(.C) Status, /// Signals an event. - signalEvent: extern fn (Event) Status, + signalEvent: fn (Event) callconv(.C) Status, /// Closes an event. - closeEvent: extern fn (Event) Status, + closeEvent: fn (Event) callconv(.C) Status, /// Checks whether an event is in the signaled state. - checkEvent: extern fn (Event) Status, + checkEvent: fn (Event) callconv(.C) Status, installProtocolInterface: Status, // TODO reinstallProtocolInterface: Status, // TODO uninstallProtocolInterface: Status, // TODO /// Queries a handle to determine if it supports a specified protocol. - handleProtocol: extern fn (Handle, *align(8) const Guid, *?*c_void) Status, + handleProtocol: fn (Handle, *align(8) const Guid, *?*c_void) callconv(.C) Status, reserved: *c_void, registerProtocolNotify: Status, // TODO /// Returns an array of handles that support a specified protocol. - locateHandle: extern fn (LocateSearchType, ?*align(8) const Guid, ?*const c_void, *usize, [*]Handle) Status, + locateHandle: fn (LocateSearchType, ?*align(8) const Guid, ?*const c_void, *usize, [*]Handle) callconv(.C) Status, locateDevicePath: Status, // TODO installConfigurationTable: Status, // TODO /// Loads an EFI image into memory. - loadImage: extern fn (bool, Handle, ?*const DevicePathProtocol, ?[*]const u8, usize, *?Handle) Status, + loadImage: fn (bool, Handle, ?*const DevicePathProtocol, ?[*]const u8, usize, *?Handle) callconv(.C) Status, /// Transfers control to a loaded image's entry point. - startImage: extern fn (Handle, ?*usize, ?*[*]u16) Status, + startImage: fn (Handle, ?*usize, ?*[*]u16) callconv(.C) Status, /// Terminates a loaded EFI image and returns control to boot services. - exit: extern fn (Handle, Status, usize, ?*const c_void) Status, + exit: fn (Handle, Status, usize, ?*const c_void) callconv(.C) Status, /// Unloads an image. - unloadImage: extern fn (Handle) Status, + unloadImage: fn (Handle) callconv(.C) Status, /// Terminates all boot services. - exitBootServices: extern fn (Handle, usize) Status, + exitBootServices: fn (Handle, usize) callconv(.C) Status, /// Returns a monotonically increasing count for the platform. - getNextMonotonicCount: extern fn (*u64) Status, + getNextMonotonicCount: fn (*u64) callconv(.C) Status, /// Induces a fine-grained stall. - stall: extern fn (usize) Status, + stall: fn (usize) callconv(.C) Status, /// Sets the system's watchdog timer. - setWatchdogTimer: extern fn (usize, u64, usize, ?[*]const u16) Status, + setWatchdogTimer: fn (usize, u64, usize, ?[*]const u16) callconv(.C) Status, connectController: Status, // TODO disconnectController: Status, // TODO /// Queries a handle to determine if it supports a specified protocol. - openProtocol: extern fn (Handle, *align(8) const Guid, *?*c_void, ?Handle, ?Handle, OpenProtocolAttributes) Status, + openProtocol: fn (Handle, *align(8) const Guid, *?*c_void, ?Handle, ?Handle, OpenProtocolAttributes) callconv(.C) Status, /// Closes a protocol on a handle that was opened using openProtocol(). - closeProtocol: extern fn (Handle, *align(8) const Guid, Handle, ?Handle) Status, + closeProtocol: fn (Handle, *align(8) const Guid, Handle, ?Handle) callconv(.C) Status, /// Retrieves the list of agents that currently have a protocol interface opened. - openProtocolInformation: extern fn (Handle, *align(8) const Guid, *[*]ProtocolInformationEntry, *usize) Status, + openProtocolInformation: fn (Handle, *align(8) const Guid, *[*]ProtocolInformationEntry, *usize) callconv(.C) Status, /// Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool. - protocolsPerHandle: extern fn (Handle, *[*]*align(8) const Guid, *usize) Status, + protocolsPerHandle: fn (Handle, *[*]*align(8) const Guid, *usize) callconv(.C) Status, /// Returns an array of handles that support the requested protocol in a buffer allocated from pool. - locateHandleBuffer: extern fn (LocateSearchType, ?*align(8) const Guid, ?*const c_void, *usize, *[*]Handle) Status, + locateHandleBuffer: fn (LocateSearchType, ?*align(8) const Guid, ?*const c_void, *usize, *[*]Handle) callconv(.C) Status, /// Returns the first protocol instance that matches the given protocol. - locateProtocol: extern fn (*align(8) const Guid, ?*const c_void, *?*c_void) Status, + locateProtocol: fn (*align(8) const Guid, ?*const c_void, *?*c_void) callconv(.C) Status, installMultipleProtocolInterfaces: Status, // TODO uninstallMultipleProtocolInterfaces: Status, // TODO /// Computes and returns a 32-bit CRC for a data buffer. - calculateCrc32: extern fn ([*]const u8, usize, *u32) Status, + calculateCrc32: fn ([*]const u8, usize, *u32) callconv(.C) Status, /// Copies the contents of one buffer to another buffer - copyMem: extern fn ([*]u8, [*]const u8, usize) void, + copyMem: fn ([*]u8, [*]const u8, usize) callconv(.C) void, /// Fills a buffer with a specified value - setMem: extern fn ([*]u8, usize, u8) void, + setMem: fn ([*]u8, usize, u8) callconv(.C) void, createEventEx: Status, // TODO diff --git a/lib/std/os/uefi/tables/runtime_services.zig b/lib/std/os/uefi/tables/runtime_services.zig index 1f0c7efad4..981e07275b 100644 --- a/lib/std/os/uefi/tables/runtime_services.zig +++ b/lib/std/os/uefi/tables/runtime_services.zig @@ -17,7 +17,7 @@ pub const RuntimeServices = extern struct { hdr: TableHeader, /// Returns the current time and date information, and the time-keeping capabilities of the hardware platform. - getTime: extern fn (*uefi.Time, ?*TimeCapabilities) Status, + getTime: fn (*uefi.Time, ?*TimeCapabilities) callconv(.C) Status, setTime: Status, // TODO getWakeupTime: Status, // TODO @@ -26,18 +26,18 @@ pub const RuntimeServices = extern struct { convertPointer: Status, // TODO /// Returns the value of a variable. - getVariable: extern fn ([*:0]const u16, *align(8) const Guid, ?*u32, *usize, ?*c_void) Status, + getVariable: fn ([*:0]const u16, *align(8) const Guid, ?*u32, *usize, ?*c_void) callconv(.C) Status, /// Enumerates the current variable names. - getNextVariableName: extern fn (*usize, [*:0]u16, *align(8) Guid) Status, + getNextVariableName: fn (*usize, [*:0]u16, *align(8) Guid) callconv(.C) Status, /// Sets the value of a variable. - setVariable: extern fn ([*:0]const u16, *align(8) const Guid, u32, usize, *c_void) Status, + setVariable: fn ([*:0]const u16, *align(8) const Guid, u32, usize, *c_void) callconv(.C) Status, getNextHighMonotonicCount: Status, // TODO /// Resets the entire platform. - resetSystem: extern fn (ResetType, Status, usize, ?*const c_void) noreturn, + resetSystem: fn (ResetType, Status, usize, ?*const c_void) callconv(.C) noreturn, updateCapsule: Status, // TODO queryCapsuleCapabilities: Status, // TODO diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig index a1a60b1798..191e8deded 100644 --- a/lib/std/os/windows/bits.zig +++ b/lib/std/os/windows/bits.zig @@ -627,7 +627,7 @@ pub const MEM_RESERVE_PLACEHOLDERS = 0x2; pub const MEM_DECOMMIT = 0x4000; pub const MEM_RELEASE = 0x8000; -pub const PTHREAD_START_ROUTINE = extern fn (LPVOID) DWORD; +pub const PTHREAD_START_ROUTINE = fn (LPVOID) callconv(.C) DWORD; pub const LPTHREAD_START_ROUTINE = PTHREAD_START_ROUTINE; pub const WIN32_FIND_DATAW = extern struct { @@ -784,7 +784,7 @@ pub const IMAGE_TLS_DIRECTORY = extern struct { pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY; pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY; -pub const PIMAGE_TLS_CALLBACK = ?extern fn (PVOID, DWORD, PVOID) void; +pub const PIMAGE_TLS_CALLBACK = ?fn (PVOID, DWORD, PVOID) callconv(.C) void; pub const PROV_RSA_FULL = 1; @@ -810,7 +810,7 @@ pub const FILE_ACTION_MODIFIED = 0x00000003; pub const FILE_ACTION_RENAMED_OLD_NAME = 0x00000004; pub const FILE_ACTION_RENAMED_NEW_NAME = 0x00000005; -pub const LPOVERLAPPED_COMPLETION_ROUTINE = ?extern fn (DWORD, DWORD, *OVERLAPPED) void; +pub const LPOVERLAPPED_COMPLETION_ROUTINE = ?fn (DWORD, DWORD, *OVERLAPPED) callconv(.C) void; pub const FILE_NOTIFY_CHANGE_CREATION = 64; pub const FILE_NOTIFY_CHANGE_SIZE = 8; @@ -863,7 +863,7 @@ pub const RTL_CRITICAL_SECTION = extern struct { pub const CRITICAL_SECTION = RTL_CRITICAL_SECTION; pub const INIT_ONCE = RTL_RUN_ONCE; pub const INIT_ONCE_STATIC_INIT = RTL_RUN_ONCE_INIT; -pub const INIT_ONCE_FN = extern fn (InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) BOOL; +pub const INIT_ONCE_FN = fn (InitOnce: *INIT_ONCE, Parameter: ?*c_void, Context: ?*c_void) callconv(.C) BOOL; pub const RTL_RUN_ONCE = extern struct { Ptr: ?*c_void, @@ -1418,7 +1418,7 @@ pub const RTL_DRIVE_LETTER_CURDIR = extern struct { DosPath: UNICODE_STRING, }; -pub const PPS_POST_PROCESS_INIT_ROUTINE = ?extern fn () void; +pub const PPS_POST_PROCESS_INIT_ROUTINE = ?fn () callconv(.C) void; pub const FILE_BOTH_DIR_INFORMATION = extern struct { NextEntryOffset: ULONG, @@ -1438,7 +1438,7 @@ pub const FILE_BOTH_DIR_INFORMATION = extern struct { }; pub const FILE_BOTH_DIRECTORY_INFORMATION = FILE_BOTH_DIR_INFORMATION; -pub const IO_APC_ROUTINE = extern fn (PVOID, *IO_STATUS_BLOCK, ULONG) void; +pub const IO_APC_ROUTINE = fn (PVOID, *IO_STATUS_BLOCK, ULONG) callconv(.C) void; pub const CURDIR = extern struct { DosPath: UNICODE_STRING, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index 31547036ae..d467a60d17 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -106,7 +106,7 @@ pub const WSAOVERLAPPED = extern struct { hEvent: ?WSAEVENT, }; -pub const WSAOVERLAPPED_COMPLETION_ROUTINE = extern fn (dwError: DWORD, cbTransferred: DWORD, lpOverlapped: *WSAOVERLAPPED, dwFlags: DWORD) void; +pub const WSAOVERLAPPED_COMPLETION_ROUTINE = fn (dwError: DWORD, cbTransferred: DWORD, lpOverlapped: *WSAOVERLAPPED, dwFlags: DWORD) callconv(.C) void; pub const ADDRESS_FAMILY = u16; diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index 6dd208e3b4..7403cca9c2 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -34,7 +34,7 @@ pub fn main() anyerror!void { std.heap.page_allocator.free(async_frame_buffer); async_frame_buffer = try std.heap.page_allocator.alignedAlloc(u8, std.Target.stack_align, size); } - const casted_fn = @ptrCast(async fn () anyerror!void, test_fn.func); + const casted_fn = @ptrCast(fn () callconv(.Async) anyerror!void, test_fn.func); break :blk await @asyncCall(async_frame_buffer, {}, casted_fn); }, .blocking => { diff --git a/lib/std/start.zig b/lib/std/start.zig index 631bb2e9f8..604c22101c 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -224,8 +224,7 @@ inline fn initEventLoopAndCallMain() u8 { // and we want fewer call frames in stack traces. return @call(.{ .modifier = .always_inline }, callMain, .{}); } - -async fn callMainAsync(loop: *std.event.Loop) u8 { +fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 { // This prevents the event loop from terminating at least until main() has returned. loop.beginOneEvent(); defer loop.finishOneEvent(); diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 57c8496c6f..b3d67aab25 100644 --- a/src-self-hosted/clang.zig +++ b/src-self-hosted/clang.zig @@ -781,7 +781,7 @@ pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigCla pub extern fn ZigClangASTContext_getPointerType(self: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType; pub extern fn ZigClangASTUnit_getASTContext(self: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext; pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager; -pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool; +pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?fn (?*c_void, *const struct_ZigClangDecl) callconv(.C) bool) bool; pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) *const struct_ZigClangRecordDecl; pub extern fn ZigClangTagDecl_isThisDeclarationADefinition(self: *const ZigClangTagDecl) bool; pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) *const struct_ZigClangEnumDecl; diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index b7535fca6f..05eb7212dd 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -41,7 +41,7 @@ const usage = const Command = struct { name: []const u8, - exec: async fn (*Allocator, []const []const u8) anyerror!void, + exec: fn (*Allocator, []const []const u8) callconv(.Async) anyerror!void, }; pub fn main() !void { @@ -713,8 +713,7 @@ const FmtError = error{ FileBusy, CurrentWorkingDirectoryUnlinked, } || fs.File.OpenError; - -async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void { +fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) callconv(.Async) FmtError!void { const stderr_file = io.getStdErr(); const stderr = stderr_file.outStream(); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index 4f6ace9899..30df7f64aa 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -112,12 +112,12 @@ test "@frameSize" { const S = struct { fn doTheTest() void { { - var ptr = @ptrCast(async fn (i32) void, other); + var ptr = @ptrCast(fn (i32) callconv(.Async) void, other); const size = @frameSize(ptr); expect(size == @sizeOf(@Frame(other))); } { - var ptr = @ptrCast(async fn () void, first); + var ptr = @ptrCast(fn () callconv(.Async) void, first); const size = @frameSize(ptr); expect(size == @sizeOf(@Frame(first))); } @@ -184,7 +184,7 @@ test "coroutine suspend with block" { var a_promise: anyframe = undefined; var global_result = false; -async fn testSuspendBlock() void { +fn testSuspendBlock() callconv(.Async) void { suspend { comptime expect(@TypeOf(@frame()) == *@Frame(testSuspendBlock)); a_promise = @frame(); @@ -209,14 +209,14 @@ test "coroutine await" { expect(await_final_result == 1234); expect(std.mem.eql(u8, &await_points, "abcdefghi")); } -async fn await_amain() void { +fn await_amain() callconv(.Async) void { await_seq('b'); var p = async await_another(); await_seq('e'); await_final_result = await p; await_seq('h'); } -async fn await_another() i32 { +fn await_another() callconv(.Async) i32 { await_seq('c'); suspend { await_seq('d'); @@ -243,14 +243,14 @@ test "coroutine await early return" { expect(early_final_result == 1234); expect(std.mem.eql(u8, &early_points, "abcdef")); } -async fn early_amain() void { +fn early_amain() callconv(.Async) void { early_seq('b'); var p = async early_another(); early_seq('d'); early_final_result = await p; early_seq('e'); } -async fn early_another() i32 { +fn early_another() callconv(.Async) i32 { early_seq('c'); return 1234; } @@ -266,7 +266,7 @@ fn early_seq(c: u8) void { test "async function with dot syntax" { const S = struct { var y: i32 = 1; - async fn foo() void { + fn foo() callconv(.Async) void { y += 1; suspend; } @@ -278,7 +278,7 @@ test "async function with dot syntax" { test "async fn pointer in a struct field" { var data: i32 = 1; const Foo = struct { - bar: async fn (*i32) void, + bar: fn (*i32) callconv(.Async) void, }; var foo = Foo{ .bar = simpleAsyncFn2 }; var bytes: [64]u8 align(16) = undefined; @@ -294,8 +294,7 @@ test "async fn pointer in a struct field" { fn doTheAwait(f: anyframe->void) void { await f; } - -async fn simpleAsyncFn2(y: *i32) void { +fn simpleAsyncFn2(y: *i32) callconv(.Async) void { defer y.* += 2; y.* += 1; suspend; @@ -303,11 +302,10 @@ async fn simpleAsyncFn2(y: *i32) void { test "@asyncCall with return type" { const Foo = struct { - bar: async fn () i32, + bar: fn () callconv(.Async) i32, var global_frame: anyframe = undefined; - - async fn middle() i32 { + fn middle() callconv(.Async) i32 { return afunc(); } @@ -338,8 +336,7 @@ test "async fn with inferred error set" { resume global_frame; std.testing.expectError(error.Fail, result); } - - async fn middle() !void { + fn middle() callconv(.Async) !void { var f = async middle2(); return await f; } @@ -376,11 +373,11 @@ fn nonFailing() (anyframe->anyerror!void) { Static.frame = async suspendThenFail(); return &Static.frame; } -async fn suspendThenFail() anyerror!void { +fn suspendThenFail() callconv(.Async) anyerror!void { suspend; return error.Fail; } -async fn printTrace(p: anyframe->(anyerror!void)) void { +fn printTrace(p: anyframe->(anyerror!void)) callconv(.Async) void { (await p) catch |e| { std.testing.expect(e == error.Fail); if (@errorReturnTrace()) |trace| { @@ -397,7 +394,7 @@ test "break from suspend" { const p = async testBreakFromSuspend(&my_result); std.testing.expect(my_result == 2); } -async fn testBreakFromSuspend(my_result: *i32) void { +fn testBreakFromSuspend(my_result: *i32) callconv(.Async) void { suspend { resume @frame(); } @@ -826,7 +823,7 @@ test "cast fn to async fn when it is inferred to be async" { var ok = false; fn doTheTest() void { - var ptr: async fn () i32 = undefined; + var ptr: fn () callconv(.Async) i32 = undefined; ptr = func; var buf: [100]u8 align(16) = undefined; var result: i32 = undefined; @@ -854,7 +851,7 @@ test "cast fn to async fn when it is inferred to be async, awaited directly" { var ok = false; fn doTheTest() void { - var ptr: async fn () i32 = undefined; + var ptr: fn () callconv(.Async) i32 = undefined; ptr = func; var buf: [100]u8 align(16) = undefined; var result: i32 = undefined; @@ -958,8 +955,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" { resume global_frame; std.testing.expectError(error.Fail, result); } - - async fn middle() !void { + fn middle() callconv(.Async) !void { var f = async middle2(); return await f; } @@ -993,7 +989,7 @@ test "@asyncCall with actual frame instead of byte buffer" { test "@asyncCall using the result location inside the frame" { const S = struct { - async fn simple2(y: *i32) i32 { + fn simple2(y: *i32) callconv(.Async) i32 { defer y.* += 2; y.* += 1; suspend; @@ -1005,7 +1001,7 @@ test "@asyncCall using the result location inside the frame" { }; var data: i32 = 1; const Foo = struct { - bar: async fn (*i32) i32, + bar: fn (*i32) callconv(.Async) i32, }; var foo = Foo{ .bar = S.simple2 }; var bytes: [64]u8 align(16) = undefined; @@ -1115,7 +1111,7 @@ test "await used in expression and awaiting fn with no suspend but async calling const sum = (await f1) + (await f2); expect(sum == 10); } - async fn add(a: i32, b: i32) i32 { + fn add(a: i32, b: i32) callconv(.Async) i32 { return a + b; } }; @@ -1130,7 +1126,7 @@ test "await used in expression after a fn call" { sum = foo() + await f1; expect(sum == 8); } - async fn add(a: i32, b: i32) i32 { + fn add(a: i32, b: i32) callconv(.Async) i32 { return a + b; } fn foo() i32 { @@ -1147,7 +1143,7 @@ test "async fn call used in expression after a fn call" { sum = foo() + add(3, 4); expect(sum == 8); } - async fn add(a: i32, b: i32) i32 { + fn add(a: i32, b: i32) callconv(.Async) i32 { return a + b; } fn foo() i32 { @@ -1403,7 +1399,7 @@ test "async function call resolves target fn frame, runtime func" { fn foo() anyerror!void { const stack_size = 1000; var stack_frame: [stack_size]u8 align(std.Target.stack_align) = undefined; - var func: async fn () anyerror!void = bar; + var func: fn () callconv(.Async) anyerror!void = bar; return await @asyncCall(&stack_frame, {}, func); } diff --git a/test/stage1/behavior/await_struct.zig b/test/stage1/behavior/await_struct.zig index 2d4faadc27..328f8f87fd 100644 --- a/test/stage1/behavior/await_struct.zig +++ b/test/stage1/behavior/await_struct.zig @@ -18,14 +18,14 @@ test "coroutine await struct" { expect(await_final_result.x == 1234); expect(std.mem.eql(u8, &await_points, "abcdefghi")); } -async fn await_amain() void { +fn await_amain() callconv(.Async) void { await_seq('b'); var p = async await_another(); await_seq('e'); await_final_result = await p; await_seq('h'); } -async fn await_another() Foo { +fn await_another() callconv(.Async) Foo { await_seq('c'); suspend { await_seq('d'); diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index 63bf055aca..8717c8e619 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -762,7 +762,7 @@ test "variable initialization uses result locations properly with regards to the test "cast between [*c]T and ?[*:0]T on fn parameter" { const S = struct { - const Handler = ?extern fn ([*c]const u8) void; + const Handler = ?fn ([*c]const u8) callconv(.C) void; fn addCallback(handler: Handler) void {} fn myCallback(cstr: ?[*:0]const u8) callconv(.C) void {} From 54088fe6e11f193590e22a12da2cc95be38129d8 Mon Sep 17 00:00:00 2001 From: StrangeBug Date: Tue, 5 May 2020 18:09:32 +0200 Subject: [PATCH 19/74] Add support for external links and URL to markdown parser. --- lib/std/special/docs/main.js | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/std/special/docs/main.js b/lib/std/special/docs/main.js index b11e10caa7..7c4cceb31b 100644 --- a/lib/std/special/docs/main.js +++ b/lib/std/special/docs/main.js @@ -1498,6 +1498,22 @@ } ]; + // Links, images and inner links don't use the same marker to wrap their content. + const linksFormat = [ + { + prefix: "[", + regex: /\[([^\]]*)\]\(([^\)]*)\)/, + urlIndex: 2, // Index in the match that contains the link URL + textIndex: 1 // Index in the match that contains the link text + }, + { + prefix: "h", + regex: /http[s]?:\/\/[^\s]+/, + urlIndex: 0, + textIndex: 0 + } + ]; + const stack = []; var innerHTML = ""; @@ -1548,6 +1564,29 @@ currentRun += innerText[i]; in_code = true; } else { + var foundMatches = false; + + for (var j = 0; j < linksFormat.length; j++) { + const linkFmt = linksFormat[j]; + + if (linkFmt.prefix == innerText[i]) { + var remaining = innerText.substring(i); + var matches = remaining.match(linkFmt.regex); + + if (matches) { + flushRun(); + innerHTML += ' ' + matches[linkFmt.textIndex] + ' '; + i += matches[0].length; // Skip the fragment we just consumed + foundMatches = true; + break; + } + } + } + + if (foundMatches) { + continue; + } + var any = false; for (var idx = (stack.length > 0 ? -1 : 0); idx < formats.length; idx++) { const fmt = idx >= 0 ? formats[idx] : stack[stack.length - 1]; From 84a0a9688caea0f7cfe19bac07d5b5d46a06d470 Mon Sep 17 00:00:00 2001 From: Tadeo Kondrak Date: Mon, 4 May 2020 10:50:11 -0600 Subject: [PATCH 20/74] update docs/tests for async/extern fn removal --- doc/langref.html.in | 4 ++-- lib/std/zig/parser_test.zig | 1 + test/compile_errors.zig | 22 +++++++++++----------- test/runtime_safety.zig | 8 ++++---- test/stack_traces.zig | 2 +- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index b2e1f6e6f6..91665604f7 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -6713,7 +6713,7 @@ const assert = std.debug.assert; test "async fn pointer in a struct field" { var data: i32 = 1; const Foo = struct { - bar: async fn (*i32) void, + bar: fn (*i32) callconv(.Async) void, }; var foo = Foo{ .bar = func }; var bytes: [64]u8 align(@alignOf(@Frame(func))) = undefined; @@ -6723,7 +6723,7 @@ test "async fn pointer in a struct field" { assert(data == 4); } -async fn func(y: *i32) void { +fn func(y: *i32) void { defer y.* += 2; y.* += 1; suspend; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 7ab3e86b1a..b98e8c69c3 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -2910,6 +2910,7 @@ test "zig fmt: noasync to nosuspend" { \\pub fn main() void { \\ nosuspend call(); \\} + \\ ); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 19ec55d9e6..a79c8825a1 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -802,7 +802,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); cases.add("exported async function", - \\export async fn foo() void {} + \\export fn foo() callconv(.Async) void {} , &[_][]const u8{ "tmp.zig:1:1: error: exported function cannot be async", }); @@ -1281,11 +1281,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { cases.add("bad alignment in @asyncCall", \\export fn entry() void { - \\ var ptr: async fn () void = func; + \\ var ptr: fn () callconv(.Async) void = func; \\ var bytes: [64]u8 = undefined; \\ _ = @asyncCall(&bytes, {}, ptr); \\} - \\async fn func() void {} + \\fn func() callconv(.Async) void {} , &[_][]const u8{ "tmp.zig:4:21: error: expected type '[]align(16) u8', found '*[64]u8'", }); @@ -1431,7 +1431,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ _ = async amain(); \\} - \\async fn amain() void { + \\fn amain() callconv(.Async) void { \\ other(); \\} \\fn other() void { @@ -1447,7 +1447,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ _ = async amain(); \\} - \\async fn amain() void { + \\fn amain() callconv(.Async) void { \\ var x: [@sizeOf(@Frame(amain))]u8 = undefined; \\} , &[_][]const u8{ @@ -1474,7 +1474,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ var ptr = afunc; \\ _ = ptr(); \\} - \\async fn afunc() void {} + \\fn afunc() callconv(.Async) void {} , &[_][]const u8{ "tmp.zig:6:12: error: function is not comptime-known; @asyncCall required", }); @@ -1485,7 +1485,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ _ = async ptr(); \\} \\ - \\async fn afunc() void { } + \\fn afunc() callconv(.Async) void { } , &[_][]const u8{ "tmp.zig:3:15: error: function is not comptime-known; @asyncCall required", }); @@ -3074,7 +3074,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ _ = async foo(); \\} - \\async fn foo() void { + \\fn foo() void { \\ suspend { \\ suspend { \\ } @@ -3122,7 +3122,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\export fn entry() void { \\ _ = async amain(); \\} - \\async fn amain() void { + \\fn amain() callconv(.Async) void { \\ return error.ShouldBeCompileError; \\} , &[_][]const u8{ @@ -3592,7 +3592,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { }); cases.add("attempt to use 0 bit type in extern fn", - \\extern fn foo(ptr: extern fn(*void) void) void; + \\extern fn foo(ptr: fn(*void) callconv(.C) void) void; \\ \\export fn entry() void { \\ foo(bar); @@ -3603,7 +3603,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { \\ bar(&{}); \\} , &[_][]const u8{ - "tmp.zig:1:30: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'", + "tmp.zig:1:23: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'", "tmp.zig:7:11: error: parameter of type '*void' has 0 bits; not allowed in function with calling convention 'C'", }); diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 6837efe2d2..2e50c3a84c 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -282,7 +282,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ var ptr = other; \\ var frame = @asyncCall(&bytes, {}, ptr); \\} - \\async fn other() void { + \\fn other() callconv(.Async) void { \\ suspend; \\} ); @@ -874,16 +874,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\ return &failing_frame; \\} \\ - \\async fn failing() anyerror!void { + \\fn failing() anyerror!void { \\ suspend; \\ return second(); \\} \\ - \\async fn second() anyerror!void { + \\fn second() callconv(.Async) anyerror!void { \\ return error.Fail; \\} \\ - \\async fn printTrace(p: anyframe->anyerror!void) void { + \\fn printTrace(p: anyframe->anyerror!void) void { \\ (await p) catch unreachable; \\} ); diff --git a/test/stack_traces.zig b/test/stack_traces.zig index 2f7201e71d..616136b9ee 100644 --- a/test/stack_traces.zig +++ b/test/stack_traces.zig @@ -282,7 +282,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { \\source.zig:10:8: [address] in main (test) \\ foo(); \\ ^ - \\start.zig:250:29: [address] in std.start.posixCallMainAndExit (test) + \\start.zig:249:29: [address] in std.start.posixCallMainAndExit (test) \\ return root.main(); \\ ^ \\start.zig:123:5: [address] in std.start._start (test) From 0a2104689b4c3c686f2268b5053ad38fd01c1d55 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 May 2020 12:45:39 -0400 Subject: [PATCH 21/74] fix incorrect flags being set in os.setSockFlags fixes networking stuff on darwin --- lib/std/os.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 86130ed32c..74d7ec8d81 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -3283,7 +3283,7 @@ fn setSockFlags(fd: fd_t, flags: u32) !void { error.Locked => unreachable, else => |e| return e, }; - if ((flags & SOCK_NONBLOCK) != 0) fd_flags |= FD_CLOEXEC; + if ((flags & SOCK_CLOEXEC) != 0) fd_flags |= FD_CLOEXEC; _ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, @@ -3296,7 +3296,7 @@ fn setSockFlags(fd: fd_t, flags: u32) !void { error.Locked => unreachable, else => |e| return e, }; - if ((flags & SOCK_CLOEXEC) != 0) fl_flags |= O_NONBLOCK; + if ((flags & SOCK_NONBLOCK) != 0) fl_flags |= O_NONBLOCK; _ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, From b13a02ed1aaab407a29b37bb5559639bf3a69715 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 May 2020 12:50:50 -0400 Subject: [PATCH 22/74] avoid unnecessary fcntl syscalls when setting socket flags --- lib/std/os.zig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 74d7ec8d81..7e50ad256a 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2173,7 +2173,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!fd_t { switch (errno(rc)) { 0 => { const fd = @intCast(fd_t, rc); - if (!have_sock_flags and filtered_sock_type != socket_type) { + if (!have_sock_flags) { try setSockFlags(fd, socket_type); } return fd; @@ -2341,7 +2341,7 @@ pub fn accept( switch (errno(rc)) { 0 => { const fd = @intCast(fd_t, rc); - if (!have_accept4 and flags != 0) { + if (!have_accept4) { try setSockFlags(fd, flags); } return fd; @@ -3277,26 +3277,26 @@ pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { } fn setSockFlags(fd: fd_t, flags: u32) !void { - { + if ((flags & SOCK_CLOEXEC) != 0) { var fd_flags = fcntl(fd, F_GETFD, 0) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, else => |e| return e, }; - if ((flags & SOCK_CLOEXEC) != 0) fd_flags |= FD_CLOEXEC; + fd_flags |= FD_CLOEXEC; _ = fcntl(fd, F_SETFD, fd_flags) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, else => |e| return e, }; } - { + if ((flags & SOCK_NONBLOCK) != 0) { var fl_flags = fcntl(fd, F_GETFL, 0) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, else => |e| return e, }; - if ((flags & SOCK_NONBLOCK) != 0) fl_flags |= O_NONBLOCK; + fl_flags |= O_NONBLOCK; _ = fcntl(fd, F_SETFL, fl_flags) catch |err| switch (err) { error.FileBusy => unreachable, error.Locked => unreachable, From a39cb034ea0ae4f608ebcd7fa98df5d58d638668 Mon Sep 17 00:00:00 2001 From: Haze Booth Date: Tue, 5 May 2020 11:49:33 -0400 Subject: [PATCH 23/74] Add setUseTestEventedIO for test steps in build.zig --- lib/std/build.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/build.zig b/lib/std/build.zig index 85a65393ec..2b7eb254ee 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1132,6 +1132,7 @@ pub const LibExeObjStep = struct { name_prefix: []const u8, filter: ?[]const u8, single_threaded: bool, + evented_io: bool = false, code_model: builtin.CodeModel = .default, root_src: ?FileSource, @@ -1559,6 +1560,11 @@ pub const LibExeObjStep = struct { self.filter = text; } + pub fn setUseTestEventedIo(self: *LibExeObjStep, use_evented_io: bool) void { + assert(self.kind == Kind.Test); + self.evented_io = use_evented_io; + } + pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void { self.addCSourceFileSource(.{ .args = args, @@ -1864,6 +1870,10 @@ pub const LibExeObjStep = struct { try zig_args.append(filter); } + if (self.evented_io) { + try zig_args.append("--test-evented-io"); + } + if (self.name_prefix.len != 0) { try zig_args.append("--test-name-prefix"); try zig_args.append(self.name_prefix); From 6f3d76f61ef7f94598c77907e5083608d223a616 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 5 May 2020 15:18:04 -0400 Subject: [PATCH 24/74] simplify test-evented-io build setting --- lib/std/build.zig | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 2b7eb254ee..8a38383e87 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1132,7 +1132,7 @@ pub const LibExeObjStep = struct { name_prefix: []const u8, filter: ?[]const u8, single_threaded: bool, - evented_io: bool = false, + test_evented_io: bool = false, code_model: builtin.CodeModel = .default, root_src: ?FileSource, @@ -1560,11 +1560,6 @@ pub const LibExeObjStep = struct { self.filter = text; } - pub fn setUseTestEventedIo(self: *LibExeObjStep, use_evented_io: bool) void { - assert(self.kind == Kind.Test); - self.evented_io = use_evented_io; - } - pub fn addCSourceFile(self: *LibExeObjStep, file: []const u8, args: []const []const u8) void { self.addCSourceFileSource(.{ .args = args, @@ -1870,7 +1865,7 @@ pub const LibExeObjStep = struct { try zig_args.append(filter); } - if (self.evented_io) { + if (self.test_evented_io) { try zig_args.append("--test-evented-io"); } From eb4fa63d3d7f7bb04ce20f0545d5d4f14aa05c89 Mon Sep 17 00:00:00 2001 From: Lann Date: Tue, 5 May 2020 19:13:35 -0400 Subject: [PATCH 25/74] Remove reference to import type (#5279) * Remove reference to import type * Improve language in `@This()` doc --- doc/langref.html.in | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 6026912893..2103a0e9e7 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -8189,9 +8189,7 @@ fn List(comptime T: type) type { {#code_end#}

When {#syntax#}@This(){#endsyntax#} is used at global scope, it returns a reference to the - current import. There is a proposal to remove the import type and use an empty struct - type instead. See - #1047 for details. + struct that corresponds to the current file.

{#header_close#} From 52f0adb3052b284102f2a96c083c5dd28b7941d8 Mon Sep 17 00:00:00 2001 From: Matthew Knight Date: Tue, 5 May 2020 23:26:00 -0700 Subject: [PATCH 26/74] checkForBuiltinTypedef now returns a string --- src-self-hosted/translate_c.zig | 74 +++++++++++++++++---------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 2a8817977b..f7b080a749 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -668,31 +668,27 @@ fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const ZigClangTypedefNameDe return transCreateNodeIdentifier(c, builtin_name); } -fn checkForBuiltinTypedef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, checked_name: []const u8) !?*ast.Node { - if (mem.eql(u8, checked_name, "uint8_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "u8") - else if (mem.eql(u8, checked_name, "int8_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "i8") - else if (mem.eql(u8, checked_name, "uint16_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "u16") - else if (mem.eql(u8, checked_name, "int16_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "i16") - else if (mem.eql(u8, checked_name, "uint32_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "u32") - else if (mem.eql(u8, checked_name, "int32_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "i32") - else if (mem.eql(u8, checked_name, "uint64_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "u64") - else if (mem.eql(u8, checked_name, "int64_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "i64") - else if (mem.eql(u8, checked_name, "intptr_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "isize") - else if (mem.eql(u8, checked_name, "uintptr_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "usize") - else if (mem.eql(u8, checked_name, "ssize_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "isize") - else if (mem.eql(u8, checked_name, "size_t")) - return transTypeDefAsBuiltin(c, typedef_decl, "usize"); +fn checkForBuiltinTypedef(checked_name: []const u8) !?[]const u8 { + const table = comptime [_][2][]const u8{ + .{ "uint8_t", "u8" }, + .{ "int8_t", "i8" }, + .{ "uint16_t", "u16" }, + .{ "int16_t", "i16" }, + .{ "uint32_t", "u32" }, + .{ "int32_t", "i32" }, + .{ "uint64_t", "u64" }, + .{ "int64_t", "i64" }, + .{ "intptr_t", "isize" }, + .{ "uintptr_t", "usize" }, + .{ "ssize_t", "isize" }, + .{ "size_t", "usize" }, + }; + + for (table) |entry| { + if (mem.eql(u8, checked_name, entry[0])) { + return entry[1]; + } + } return null; } @@ -707,8 +703,8 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; - if (try checkForBuiltinTypedef(c, typedef_decl, checked_name)) |node| { - return node; + if (try checkForBuiltinTypedef(checked_name)) |builtin| { + return transTypeDefAsBuiltin(c, typedef_decl, builtin); } if (!top_level_visit) { @@ -716,12 +712,12 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l } _ = try c.decl_table.put(@ptrToInt(ZigClangTypedefNameDecl_getCanonicalDecl(typedef_decl)), checked_name); - const node = (try transZigTypedef(rp, typedef_decl, true, checked_name)) orelse return null; + const node = (try transCreateNodeTypedef(rp, typedef_decl, true, checked_name)) orelse return null; try addTopLevelDecl(c, checked_name, &node.base); return transCreateNodeIdentifier(c, checked_name); } -fn transZigTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedefNameDecl, toplevel: bool, checked_name: []const u8) Error!?*ast.Node.VarDecl { +fn transCreateNodeTypedef(rp: RestorePoint, typedef_decl: *const ZigClangTypedefNameDecl, toplevel: bool, checked_name: []const u8) Error!?*ast.Node.VarDecl { const node = try transCreateNodeVarDecl(rp.c, toplevel, true, checked_name); node.eq_token = try appendToken(rp.c, .Equal, "="); @@ -1411,14 +1407,20 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) @ptrCast(*const ZigClangNamedDecl, typedef_decl), )); - const mangled_name = try block_scope.makeMangledName(c, name); - if (try checkForBuiltinTypedef(c, typedef_decl, mangled_name)) |ast_node| { - return ast_node; - } + const underlying_qual = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); + const underlying_type = ZigClangQualType_getTypePtr(underlying_qual); + const underlying_name = try c.str(ZigClangType_getTypeClassName(underlying_type)); - const node = (try transZigTypedef(rp, typedef_decl, false, mangled_name)) - orelse return error.UnsupportedTranslation; - try block_scope.block_node.statements.push(&node.base); + const mangled_name = try block_scope.makeMangledName(c, name); + if (try checkForBuiltinTypedef(underlying_name)) |builtin| { + try block_scope.variables.push(.{ + .alias = builtin, + .name = mangled_name, + }); + } else { + const node = (try transCreateNodeTypedef(rp, typedef_decl, false, mangled_name)) orelse return error.UnsupportedTranslation; + try block_scope.block_node.statements.push(&node.base); + } }, else => |kind| return revertAndWarn( rp, From c0b269bf46d6257112f08a3c48904dd5654c97e8 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 6 May 2020 11:48:46 +0300 Subject: [PATCH 27/74] translate-c: small patch to fix bultin type detection --- src-self-hosted/translate_c.zig | 5 ++--- test/run_translated_c.zig | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index f7b080a749..b515791f77 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -669,7 +669,7 @@ fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const ZigClangTypedefNameDe } fn checkForBuiltinTypedef(checked_name: []const u8) !?[]const u8 { - const table = comptime [_][2][]const u8{ + const table = [_][2][]const u8{ .{ "uint8_t", "u8" }, .{ "int8_t", "i8" }, .{ "uint16_t", "u16" }, @@ -1409,10 +1409,9 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) const underlying_qual = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl); const underlying_type = ZigClangQualType_getTypePtr(underlying_qual); - const underlying_name = try c.str(ZigClangType_getTypeClassName(underlying_type)); const mangled_name = try block_scope.makeMangledName(c, name); - if (try checkForBuiltinTypedef(underlying_name)) |builtin| { + if (try checkForBuiltinTypedef(name)) |builtin| { try block_scope.variables.push(.{ .alias = builtin, .name = mangled_name, diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig index 83569f1241..7dc64f068f 100644 --- a/test/run_translated_c.zig +++ b/test/run_translated_c.zig @@ -245,12 +245,12 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { , ""); cases.add("scoped typedef", - \\#include \\int main(int argc, char **argv) { \\ typedef int Foo; \\ typedef Foo Bar; \\ typedef void (*func)(int); - \\ typedef uint32_t Number; + \\ typedef int uint32_t; + \\ uint32_t a; \\ Foo i; \\ Bar j; \\ return 0; From 0e30edd8d099f005e3d1ee4de1d130c6e5c69295 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 6 May 2020 12:52:26 +0300 Subject: [PATCH 28/74] std: handle ConnectionTimedOut in switch regression from #5266 closes #5270 --- lib/std/elf.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/std/elf.zig b/lib/std/elf.zig index 7b415f675a..f02cb33969 100644 --- a/lib/std/elf.zig +++ b/lib/std/elf.zig @@ -548,6 +548,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void { error.BrokenPipe => return error.UnableToReadElfFile, error.Unseekable => return error.UnableToReadElfFile, error.ConnectionResetByPeer => return error.UnableToReadElfFile, + error.ConnectionTimedOut => return error.UnableToReadElfFile, error.InputOutput => return error.FileSystem, error.Unexpected => return error.Unexpected, error.WouldBlock => return error.Unexpected, From 3c4abacba67830f368f0d22de796a9b531044a15 Mon Sep 17 00:00:00 2001 From: data-man Date: Wed, 6 May 2020 17:08:49 +0500 Subject: [PATCH 29/74] Optimization of vectors hashing --- lib/std/hash/auto_hash.zig | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 70c858098d..a33b23354b 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -113,11 +113,9 @@ pub fn hash(hasher: var, key: var, comptime strat: HashStrategy) void { hasher.update(mem.asBytes(&key)); } else { // Otherwise, hash every element. - // TODO remove the copy to an array once field access is done. - const array: [info.len]info.child = key; comptime var i = 0; inline while (i < info.len) : (i += 1) { - hash(hasher, array[i], strat); + hash(hasher, key[i], strat); } } }, From b336dda0765ba345253ed4b25113a5db4386c3f0 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Wed, 6 May 2020 15:36:52 +0200 Subject: [PATCH 30/74] Standard library: Fix a regression in loop.waitUntilFdWritableOrReadable This broke async io on linux. Regressed in 8ebcca6734e07aea29098ca4c63c0216b3099d0e --- lib/std/event/loop.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 15e7a3481c..04859b6205 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -493,7 +493,7 @@ pub const Loop = struct { pub fn waitUntilFdWritableOrReadable(self: *Loop, fd: os.fd_t) void { switch (builtin.os.tag) { .linux => { - self.linuxWaitFd(@intCast(usize, fd), os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN); + self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN); }, .macosx, .freebsd, .netbsd, .dragonfly => { self.bsdWaitKev(@intCast(usize, fd), os.EVFILT_READ, os.EV_ONESHOT); From 0c7397b49f8c434cf1f714c08ab37d1429ab1be7 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 6 May 2020 23:08:08 -0600 Subject: [PATCH 31/74] fix copy/paste error in AllocWithOptionaPayload --- lib/std/mem.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a40334e587..210b5cc108 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -124,9 +124,9 @@ pub const Allocator = struct { fn AllocWithOptionsPayload(comptime Elem: type, comptime alignment: ?u29, comptime sentinel: ?Elem) type { if (sentinel) |s| { - return [:s]align(alignment orelse @alignOf(T)) Elem; + return [:s]align(alignment orelse @alignOf(Elem)) Elem; } else { - return []align(alignment orelse @alignOf(T)) Elem; + return []align(alignment orelse @alignOf(Elem)) Elem; } } From 0a76e11617a76d884a52bf49c7b2b9a706e7bc8c Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Wed, 6 May 2020 23:56:48 -0600 Subject: [PATCH 32/74] add failAllocator to enable some regression tests --- lib/std/mem.zig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 210b5cc108..13fd3d05f3 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -281,6 +281,22 @@ pub const Allocator = struct { } }; +var failAllocator = Allocator { + .reallocFn = failAllocatorRealloc, + .shrinkFn = failAllocatorShrink, +}; +fn failAllocatorRealloc(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 { + return error.OutOfMemory; +} +fn failAllocatorShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 { + @panic("failAllocatorShrink should never be called because it cannot allocate"); +} + +test "mem.Allocator basics" { + testing.expectError(error.OutOfMemory, failAllocator.alloc(u8, 1)); + testing.expectError(error.OutOfMemory, failAllocator.allocSentinel(u8, 1, 0)); +} + /// Copy all of source into dest at position 0. /// dest.len must be >= source.len. /// dest.ptr must be <= src.ptr. From 25810bc1e662014185a74282abd5881778d7a55e Mon Sep 17 00:00:00 2001 From: Jens Goldberg Date: Wed, 6 May 2020 15:45:28 +0000 Subject: [PATCH 33/74] Removed duplicate WM_ACTIVATE --- lib/std/os/windows/user32.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/std/os/windows/user32.zig b/lib/std/os/windows/user32.zig index bda1fdffb6..7b82922469 100644 --- a/lib/std/os/windows/user32.zig +++ b/lib/std/os/windows/user32.zig @@ -73,7 +73,6 @@ pub const WM_XBUTTONDBLCLK = 0x020D; // WA pub const WA_INACTIVE = 0; pub const WA_ACTIVE = 0x0006; -pub const WM_ACTIVATE = 0x0006; // WS pub const WS_OVERLAPPED = 0x00000000; From 20c1696865fc859e4f02a1f7a3e2e4bf4177a2d8 Mon Sep 17 00:00:00 2001 From: Jens Goldberg Date: Thu, 7 May 2020 11:25:09 +0000 Subject: [PATCH 34/74] Removed GetModuleHandleA from user32 GetModuleHandleA is an kernel32 function and already defined there, it doesn't belong in user32. --- lib/std/os/windows/user32.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/std/os/windows/user32.zig b/lib/std/os/windows/user32.zig index 7b82922469..3877e19ad8 100644 --- a/lib/std/os/windows/user32.zig +++ b/lib/std/os/windows/user32.zig @@ -146,7 +146,6 @@ pub extern "user32" fn CreateWindowExA( pub extern "user32" fn RegisterClassExA(*const WNDCLASSEXA) callconv(.Stdcall) c_ushort; pub extern "user32" fn DefWindowProcA(HWND, Msg: UINT, WPARAM, LPARAM) callconv(.Stdcall) LRESULT; -pub extern "user32" fn GetModuleHandleA(lpModuleName: ?LPCSTR) callconv(.Stdcall) HMODULE; pub extern "user32" fn ShowWindow(hWnd: ?HWND, nCmdShow: i32) callconv(.Stdcall) bool; pub extern "user32" fn UpdateWindow(hWnd: ?HWND) callconv(.Stdcall) bool; pub extern "user32" fn GetDC(hWnd: ?HWND) callconv(.Stdcall) ?HDC; From 79bf4003da5fad5046b34d6256eeb8a575890ea5 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Wed, 6 May 2020 22:08:04 +0200 Subject: [PATCH 35/74] stage1: add ZigList gdb pretty printing --- tools/zig-gdb.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 tools/zig-gdb.py diff --git a/tools/zig-gdb.py b/tools/zig-gdb.py new file mode 100644 index 0000000000..f0efef9d2f --- /dev/null +++ b/tools/zig-gdb.py @@ -0,0 +1,39 @@ +# pretty printing for stage1 +# put "source /path/to/zig-gdb.py" in ~/.gdbinit to load it automatically + +import gdb.printing + +class ZigListPrinter: + def __init__(self, val): + self.val = val + + def to_string(self): + return '%s of length %d, capacity %d' % (self.val.type.name, int(self.val['length']), int(self.val['capacity'])) + + def children(self): + def it(ziglist): + for i in range(int(ziglist.val['length'])): + item = ziglist.val['items'] + i + yield ('[%d]' % i, item.dereference()) + return it(self) + + def display_hint(self): + return 'array' + +# handle both Buf and ZigList because Buf* doesn't work otherwise (gdb bug?) +class BufPrinter: + def __init__(self, val): + self.val = val['list'] if val.type.name == 'Buf' else val + + def to_string(self): + return self.val['items'].string(length=int(self.val['length'])) + + def display_hint(self): + return 'string' + +pp = gdb.printing.RegexpCollectionPrettyPrinter('zig') +pp.add_printer('Buf', '^Buf$', BufPrinter) +pp.add_printer('ZigList', '^ZigList$', BufPrinter) +pp.add_printer('ZigList', '^ZigList<.*>$', ZigListPrinter) + +gdb.printing.register_pretty_printer(gdb.current_objfile(), pp) From a78ac96134a28d9e8208728bc8affb99122ff4fa Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Thu, 7 May 2020 01:49:38 +0200 Subject: [PATCH 36/74] fix crash in single-threaded builds --- lib/std/event/loop.zig | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 8ef5f1d8e4..cbaa156d0e 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -616,14 +616,16 @@ pub const Loop = struct { self.workerRun(); - switch (builtin.os.tag) { - .linux, - .macosx, - .freebsd, - .netbsd, - .dragonfly, - => self.fs_thread.wait(), - else => {}, + if (!builtin.single_threaded) { + switch (builtin.os.tag) { + .linux, + .macosx, + .freebsd, + .netbsd, + .dragonfly, + => self.fs_thread.wait(), + else => {}, + } } for (self.extra_threads) |extra_thread| { From 7e8b859095a00cca8d102f0738a43e86fb4fb5f2 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Thu, 7 May 2020 01:55:19 +0200 Subject: [PATCH 37/74] fix oneshot flag erroneusly set as filter_flag --- lib/std/event/loop.zig | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index cbaa156d0e..607e2f24ca 100644 --- a/lib/std/event/loop.zig +++ b/lib/std/event/loop.zig @@ -503,7 +503,7 @@ pub const Loop = struct { } } - pub fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) callconv(.Async) void { + pub fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, flags: u16) void { var resume_node = ResumeNode.Basic{ .base = ResumeNode{ .id = ResumeNode.Id.Basic, @@ -512,21 +512,28 @@ pub const Loop = struct { }, .kev = undefined, }; - defer self.bsdRemoveKev(ident, filter); + + defer { + // If the kevent was set to be ONESHOT, it doesn't need to be deleted manually. + if (flags & os.EV_ONESHOT != 0) { + self.bsdRemoveKev(ident, filter); + } + } + suspend { - self.bsdAddKev(&resume_node, ident, filter, fflags) catch unreachable; + self.bsdAddKev(&resume_node, ident, filter, flags) catch unreachable; } } /// resume_node must live longer than the anyframe that it holds a reference to. - pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, fflags: u32) !void { + pub fn bsdAddKev(self: *Loop, resume_node: *ResumeNode.Basic, ident: usize, filter: i16, flags: u16) !void { self.beginOneEvent(); errdefer self.finishOneEvent(); var kev = [1]os.Kevent{os.Kevent{ .ident = ident, .filter = filter, - .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR, - .fflags = fflags, + .flags = os.EV_ADD | os.EV_ENABLE | os.EV_CLEAR | flags, + .fflags = 0, .data = 0, .udata = @ptrToInt(&resume_node.base), }}; From 35a59b5b0f3d827a7b3ed785be3155b72d15e682 Mon Sep 17 00:00:00 2001 From: Loris Cro Date: Thu, 7 May 2020 02:00:39 +0200 Subject: [PATCH 38/74] remove readable check when opening a socket connection --- lib/std/os.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index 7e50ad256a..1eab9affe7 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -2549,7 +2549,7 @@ pub fn connect(sockfd: fd_t, sock_addr: *const sockaddr, len: socklen_t) Connect EAFNOSUPPORT => return error.AddressFamilyNotSupported, EAGAIN, EINPROGRESS => { const loop = std.event.Loop.instance orelse return error.WouldBlock; - loop.waitUntilFdWritableOrReadable(sockfd); + loop.waitUntilFdWritable(sockfd); return getsockoptError(sockfd); }, EALREADY => unreachable, // The socket is nonblocking and a previous connection attempt has not yet been completed. From 2c9effc101f2359f6233fefb47eb850001634b42 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Thu, 7 May 2020 01:31:18 +0200 Subject: [PATCH 39/74] stage1: handle all cases of invalid struct field default value --- src/ir.cpp | 6 ++++++ test/compile_errors.zig | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 4a0fc55d74..bcd05553ed 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21697,6 +21697,9 @@ static IrInstGen *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInst* source_ins if (field->is_comptime) { IrInstGen *elem = ir_const(ira, source_instr, field_type); memoize_field_init_val(ira->codegen, struct_type, field); + if(field->init_val != nullptr && type_is_invalid(field->init_val->type)){ + return ira->codegen->invalid_inst_gen; + } copy_const_val(ira->codegen, elem->value, field->init_val); return ir_get_ref2(ira, source_instr, elem, field_type, true, false); } @@ -25053,6 +25056,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInst* source_instr, ZigTy inner_fields[3]->type = get_optional_type2(ira->codegen, struct_field->type_entry); if (inner_fields[3]->type == nullptr) return ErrorSemanticAnalyzeFail; memoize_field_init_val(ira->codegen, type_entry, struct_field); + if(struct_field->init_val != nullptr && type_is_invalid(struct_field->init_val->type)){ + return ErrorSemanticAnalyzeFail; + } set_optional_payload(inner_fields[3], struct_field->init_val); ZigValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index a79c8825a1..e85538e0ba 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -7353,4 +7353,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ":3:18: error: expected type '[*:0]const u8', found '*[64]u8'", ":3:18: note: destination pointer requires a terminating '0' sentinel", }); + + cases.add("issue #5221: invalid struct init type referenced by @typeInfo and passed into function", + \\fn ignore(comptime param: var) void {} + \\ + \\export fn foo() void { + \\ const MyStruct = struct { + \\ wrong_type: []u8 = "foo", + \\ }; + \\ + \\ comptime ignore(@typeInfo(MyStruct).Struct.fields[0]); + \\} + , &[_][]const u8{ + ":5:28: error: expected type '[]u8', found '*const [3:0]u8'", + }); } From fbf081a3066b4a438e53b58ad2aa564022dfa88d Mon Sep 17 00:00:00 2001 From: Josh Junon Date: Sat, 4 Apr 2020 04:03:06 +0200 Subject: [PATCH 40/74] add failing test for #4909 --- test/compile_errors.zig | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 19ec55d9e6..c7a771abf1 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -5375,6 +5375,50 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { break :x tc; }); + cases.addCase(x: { + const tc = cases.create("multiple files with private member instance function (canonical invocation) error", + \\const Foo = @import("foo.zig",).Foo; + \\ + \\export fn callPrivFunction() void { + \\ var foo = Foo{}; + \\ Foo.privateFunction(foo); + \\} + , &[_][]const u8{ + "tmp.zig:5:8: error: 'privateFunction' is private", + "foo.zig:2:5: note: declared here", + }); + + tc.addSourceFile("foo.zig", + \\pub const Foo = struct { + \\ fn privateFunction(self: *Foo) void { } + \\}; + ); + + break :x tc; + }); + + cases.addCase(x: { + const tc = cases.create("multiple files with private member instance function error", + \\const Foo = @import("foo.zig",).Foo; + \\ + \\export fn callPrivFunction() void { + \\ var foo = Foo{}; + \\ foo.privateFunction(); + \\} + , &[_][]const u8{ + "tmp.zig:5:8: error: 'privateFunction' is private", + "foo.zig:2:5: note: declared here", + }); + + tc.addSourceFile("foo.zig", + \\pub const Foo = struct { + \\ fn privateFunction(self: *Foo) void { } + \\}; + ); + + break :x tc; + }); + cases.add("container init with non-type", \\const zero: i32 = 0; \\const a = zero{1}; From 4a5c58dd354b84af821a6c257cc15489fc827f75 Mon Sep 17 00:00:00 2001 From: Josh Junon Date: Sat, 4 Apr 2020 04:04:00 +0200 Subject: [PATCH 41/74] fix private member checking for non-canonical invocations (fixes #4909) --- src/ir.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ir.cpp b/src/ir.cpp index 4a0fc55d74..8373ebfa70 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -21624,6 +21624,15 @@ static IrInstGen *ir_analyze_container_member_access_inner(IrAnalyze *ira, if (tld->resolution == TldResolutionResolving) return ir_error_dependency_loop(ira, source_instr); + if (tld->visib_mod == VisibModPrivate && + tld->import != get_scope_import(source_instr->scope)) + { + ErrorMsg *msg = ir_add_error(ira, source_instr, + buf_sprintf("'%s' is private", buf_ptr(field_name))); + add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); + return ira->codegen->invalid_inst_gen; + } + TldFn *tld_fn = (TldFn *)tld; ZigFn *fn_entry = tld_fn->fn_entry; assert(fn_entry != nullptr); From b6dc7fc9ffddebce6f04a5349c8f2252c457adf7 Mon Sep 17 00:00:00 2001 From: Josh Junon Date: Sat, 4 Apr 2020 04:04:40 +0200 Subject: [PATCH 42/74] publicize member functions affected by #4909 --- lib/std/build.zig | 10 +++++----- lib/std/dwarf.zig | 8 ++++---- lib/std/dynamic_library.zig | 4 ++-- lib/std/json.zig | 2 +- lib/std/pdb.zig | 2 +- lib/std/zig/cross_target.zig | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 8a38383e87..a7615292ce 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -284,11 +284,11 @@ pub const Builder = struct { return run_step; } - fn dupe(self: *Builder, bytes: []const u8) []u8 { + pub fn dupe(self: *Builder, bytes: []const u8) []u8 { return mem.dupe(self.allocator, u8, bytes) catch unreachable; } - fn dupePath(self: *Builder, bytes: []const u8) []u8 { + pub fn dupePath(self: *Builder, bytes: []const u8) []u8 { const the_copy = self.dupe(bytes); for (the_copy) |*byte| { switch (byte.*) { @@ -717,7 +717,7 @@ pub const Builder = struct { return self.invalid_user_input; } - fn spawnChild(self: *Builder, argv: []const []const u8) !void { + pub fn spawnChild(self: *Builder, argv: []const []const u8) !void { return self.spawnChildEnvMap(null, self.env_map, argv); } @@ -843,7 +843,7 @@ pub const Builder = struct { }) catch unreachable; } - fn updateFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { + pub fn updateFile(self: *Builder, source_path: []const u8, dest_path: []const u8) !void { if (self.verbose) { warn("cp {} {} ", .{ source_path, dest_path }); } @@ -855,7 +855,7 @@ pub const Builder = struct { }; } - fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { + pub fn pathFromRoot(self: *Builder, rel_path: []const u8) []u8 { return fs.path.resolve(self.allocator, &[_][]const u8{ self.build_root, rel_path }) catch unreachable; } diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index fe40a04b9d..ebb4c096f8 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -121,7 +121,7 @@ const Die = struct { }; } - fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]const u8 { + pub fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]const u8 { const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; return switch (form_value.*) { FormValue.String => |value| value, @@ -389,7 +389,7 @@ pub const DwarfInfo = struct { return self.abbrev_table_list.allocator; } - fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 { + pub fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 { for (di.func_list.span()) |*func| { if (func.pc_range) |range| { if (address >= range.start and address < range.end) { @@ -578,7 +578,7 @@ pub const DwarfInfo = struct { } } - fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { + pub fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { for (di.compile_unit_list.span()) |*compile_unit| { if (compile_unit.pc_range) |range| { if (target_address >= range.start and target_address < range.end) return compile_unit; @@ -690,7 +690,7 @@ pub const DwarfInfo = struct { return result; } - fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !debug.LineInfo { + pub fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !debug.LineInfo { var stream = io.fixedBufferStream(di.debug_line); const in = &stream.inStream(); const seekable = &stream.seekableStream(); diff --git a/lib/std/dynamic_library.zig b/lib/std/dynamic_library.zig index 70e26cc71c..65c65292bc 100644 --- a/lib/std/dynamic_library.zig +++ b/lib/std/dynamic_library.zig @@ -33,11 +33,11 @@ const LinkMap = extern struct { pub const Iterator = struct { current: ?*LinkMap, - fn end(self: *Iterator) bool { + pub fn end(self: *Iterator) bool { return self.current == null; } - fn next(self: *Iterator) ?*LinkMap { + pub fn next(self: *Iterator) ?*LinkMap { if (self.current) |it| { self.current = it.l_next; return it; diff --git a/lib/std/json.zig b/lib/std/json.zig index b2b2db6493..1e220d6708 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2336,7 +2336,7 @@ pub const StringifyOptions = struct { /// After a colon, should whitespace be inserted? separator: bool = true, - fn outputIndent( + pub fn outputIndent( whitespace: @This(), out_stream: var, ) @TypeOf(out_stream).Error!void { diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig index 75589b71ff..cd0106034e 100644 --- a/lib/std/pdb.zig +++ b/lib/std/pdb.zig @@ -708,7 +708,7 @@ const MsfStream = struct { return block * self.block_size + offset; } - fn inStream(self: *MsfStream) std.io.InStream(*MsfStream, Error, read) { + pub fn inStream(self: *MsfStream) std.io.InStream(*MsfStream, Error, read) { return .{ .context = self }; } }; diff --git a/lib/std/zig/cross_target.zig b/lib/std/zig/cross_target.zig index 8783ddcb6d..1909a07df0 100644 --- a/lib/std/zig/cross_target.zig +++ b/lib/std/zig/cross_target.zig @@ -660,7 +660,7 @@ pub const CrossTarget = struct { return Target.getObjectFormatSimple(self.getOsTag(), self.getCpuArch()); } - fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void { + pub fn updateCpuFeatures(self: CrossTarget, set: *Target.Cpu.Feature.Set) void { set.removeFeatureSet(self.cpu_features_sub); set.addFeatureSet(self.cpu_features_add); set.populateDependencies(self.getCpuArch().allFeaturesList()); From 10abffcd98f2f1ac9e8532c53820d7c1eea6d88f Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 8 May 2020 14:52:09 +0300 Subject: [PATCH 43/74] fix more private member access --- lib/std/net.zig | 2 +- lib/std/pdb.zig | 6 +++--- src-self-hosted/ir/text.zig | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/std/net.zig b/lib/std/net.zig index cc3e0d903e..aa38aeae08 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -386,7 +386,7 @@ pub const AddressList = struct { addrs: []Address, canon_name: ?[]u8, - fn deinit(self: *AddressList) void { + pub fn deinit(self: *AddressList) void { // Here we copy the arena allocator into stack memory, because // otherwise it would destroy itself while it was still working. var arena = self.arena; diff --git a/lib/std/pdb.zig b/lib/std/pdb.zig index cd0106034e..e4180717e9 100644 --- a/lib/std/pdb.zig +++ b/lib/std/pdb.zig @@ -644,7 +644,7 @@ const MsfStream = struct { return stream; } - fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { + pub fn readNullTermString(self: *MsfStream, allocator: *mem.Allocator) ![]u8 { var list = ArrayList(u8).init(allocator); while (true) { const byte = try self.inStream().readByte(); @@ -684,13 +684,13 @@ const MsfStream = struct { return buffer.len; } - fn seekBy(self: *MsfStream, len: i64) !void { + pub fn seekBy(self: *MsfStream, len: i64) !void { self.pos = @intCast(u64, @intCast(i64, self.pos) + len); if (self.pos >= self.blocks.len * self.block_size) return error.EOF; } - fn seekTo(self: *MsfStream, len: u64) !void { + pub fn seekTo(self: *MsfStream, len: u64) !void { self.pos = len; if (self.pos >= self.blocks.len * self.block_size) return error.EOF; diff --git a/src-self-hosted/ir/text.zig b/src-self-hosted/ir/text.zig index e1efb40fe5..1efcd6f599 100644 --- a/src-self-hosted/ir/text.zig +++ b/src-self-hosted/ir/text.zig @@ -236,7 +236,7 @@ pub const Inst = struct { @"comptime_int", @"comptime_float", - fn toType(self: BuiltinType) Type { + pub fn toType(self: BuiltinType) Type { return switch (self) { .@"isize" => Type.initTag(.@"isize"), .@"usize" => Type.initTag(.@"usize"), From 45f7c78bfcfe1ddef54ee2de05e9425b990de553 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Fri, 8 May 2020 22:11:03 +1000 Subject: [PATCH 44/74] std: fix RTLD_ constants on OSX --- lib/std/os/bits/darwin.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index 8a596331a6..8e4682b3f4 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -1263,10 +1263,10 @@ pub const RTLD_NOLOAD = 0x10; pub const RTLD_NODELETE = 0x80; pub const RTLD_FIRST = 0x100; -pub const RTLD_NEXT = @intToPtr(*c_void, ~maxInt(usize)); -pub const RTLD_DEFAULT = @intToPtr(*c_void, ~maxInt(usize) - 1); -pub const RTLD_SELF = @intToPtr(*c_void, ~maxInt(usize) - 2); -pub const RTLD_MAIN_ONLY = @intToPtr(*c_void, ~maxInt(usize) - 4); +pub const RTLD_NEXT = @intToPtr(*c_void, @bitCast(usize, @as(isize, -1))); +pub const RTLD_DEFAULT = @intToPtr(*c_void, @bitCast(usize, @as(isize, -2))); +pub const RTLD_SELF = @intToPtr(*c_void, @bitCast(usize, @as(isize, -3))); +pub const RTLD_MAIN_ONLY = @intToPtr(*c_void, @bitCast(usize, @as(isize, -5))); /// duplicate file descriptor pub const F_DUPFD = 0; From 336ddb5b7656367d074ab7d8a6899321a041452c Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 8 May 2020 19:02:15 +0300 Subject: [PATCH 45/74] std: add test for mem.zeroes on sentinel terminated arrays --- lib/std/mem.zig | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index cedb1bc27d..63db3d58b2 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -341,8 +341,8 @@ pub fn zeroes(comptime T: type) T { } }, .Array => |info| { - if (info.sentinel) |sentinel| { - return [_:info.sentinel]info.child{zeroes(info.child)} ** info.len; + if (info.sentinel) |sentinel| { + return [_:sentinel]info.child{zeroes(info.child)} ** info.len; } return [_]info.child{zeroes(info.child)} ** info.len; }, @@ -407,6 +407,7 @@ test "mem.zeroes" { array: [2]u32, optional_int: ?u8, empty: void, + sentinel: [3:0]u8, }; const b = zeroes(ZigStruct); @@ -431,6 +432,9 @@ test "mem.zeroes" { testing.expectEqual(@as(u32, 0), e); } testing.expectEqual(@as(?u8, null), b.optional_int); + for (b.sentinel) |e| { + testing.expectEqual(@as(u8, 0), e); + } } pub fn secureZero(comptime T: type, s: []T) void { @@ -504,7 +508,7 @@ pub const toSlice = @compileError("deprecated; use std.mem.spanZ"); /// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated, /// and assumed to not allow null. pub fn Span(comptime T: type) type { - switch(@typeInfo(T)) { + switch (@typeInfo(T)) { .Optional => |optional_info| { return ?Span(optional_info.child); }, From d4d509090b47a3860831a0fb6fb7fae02f5f7857 Mon Sep 17 00:00:00 2001 From: Vexu Date: Sat, 9 May 2020 00:31:11 +0300 Subject: [PATCH 46/74] make std.build.getInstallPath public Closes #5299 --- lib/std/build.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index a7615292ce..67f2af1047 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -985,7 +985,7 @@ pub const Builder = struct { self.search_prefixes.append(search_prefix) catch unreachable; } - fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { + pub fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 { const base_dir = switch (dir) { .Prefix => self.install_path, .Bin => self.exe_dir, From e79d7e0deda9e74dbaad1aa77db3e041f92f4f71 Mon Sep 17 00:00:00 2001 From: Haze Booth Date: Sat, 9 May 2020 08:09:55 -0400 Subject: [PATCH 47/74] Remove fs.File artifact from connectUnixSocket --- lib/std/net.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/std/net.zig b/lib/std/net.zig index aa38aeae08..4e6bd03186 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -377,7 +377,6 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { return fs.File{ .handle = sockfd, - .io_mode = std.io.mode, }; } From 0363f3c6f3017e8340ec466ef615a4bb9a08baec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=86=8A=E9=91=AB?= <1781189926@qq.com> Date: Sun, 10 May 2020 20:35:21 +0800 Subject: [PATCH 48/74] mem.eql need slice type --- doc/langref.html.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 00f82cd379..5bf91ca70f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -1565,7 +1565,7 @@ value == null{#endsyntax#} const array1 = [_]u32{1,2}; const array2 = [_]u32{3,4}; const together = array1 ++ array2; -mem.eql(u32, together, &[_]u32{1,2,3,4}){#endsyntax#} +mem.eql(u32, &together, &[_]u32{1,2,3,4}){#endsyntax#} From 204f8daeeda02738479e0d586e6426e23f78e6cc Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Mon, 11 May 2020 14:06:37 +0200 Subject: [PATCH 49/74] stage1: detect underflow in bigint_fits_in_bits --- src/bigint.cpp | 1 + test/compile_errors.zig | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/bigint.cpp b/src/bigint.cpp index dd04363e82..79a05e95a5 100644 --- a/src/bigint.cpp +++ b/src/bigint.cpp @@ -243,6 +243,7 @@ bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed) { } if (!is_signed) { + if(bn->is_negative) return false; size_t full_bits = bn->digit_count * 64; size_t leading_zero_count = bigint_clz(bn, full_bits); return bit_count >= full_bits - leading_zero_count; diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 5eb009dafa..a6e2d0b98f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -7411,4 +7411,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { , &[_][]const u8{ ":5:28: error: expected type '[]u8', found '*const [3:0]u8'", }); + + cases.add("integer underflow error", + \\export fn entry() void { + \\ _ = @intToPtr(*c_void, ~@as(usize, @import("std").math.maxInt(usize)) - 1); + \\} + , &[_][]const u8{ + ":2:75: error: operation caused overflow", + }); } From 832f6c122877b2fd6aeb45b3417e2641bd9aaec7 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Mon, 11 May 2020 09:11:05 -0600 Subject: [PATCH 50/74] make Address.getOsSockLen pub --- lib/std/net.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/net.zig b/lib/std/net.zig index 4e6bd03186..96c95fc497 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -341,7 +341,7 @@ pub const Address = extern union { return mem.eql(u8, a_bytes, b_bytes); } - fn getOsSockLen(self: Address) os.socklen_t { + pub fn getOsSockLen(self: Address) os.socklen_t { switch (self.any.family) { os.AF_INET => return @sizeOf(os.sockaddr_in), os.AF_INET6 => return @sizeOf(os.sockaddr_in6), From 0847b47bf83c699d27c903e51b20f863d47c5790 Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 12 May 2020 00:24:09 +0300 Subject: [PATCH 51/74] fix `@intToFloat` on comptime_floats --- src/ir.cpp | 12 +++++++----- test/stage1/behavior/cast.zig | 9 +++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index b5c4212ca5..6bd4e9b805 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -12760,9 +12760,7 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInst *source_instr, const_val->type = new_type; break; case CastOpIntToFloat: - { - assert(new_type->id == ZigTypeIdFloat); - + if (new_type->id == ZigTypeIdFloat) { BigFloat bigfloat; bigfloat_init_bigint(&bigfloat, &other_val->data.x_bigint); switch (new_type->data.floating.bit_count) { @@ -12783,9 +12781,13 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInst *source_instr, default: zig_unreachable(); } - const_val->special = ConstValSpecialStatic; - break; + } else if (new_type->id == ZigTypeIdComptimeFloat) { + bigfloat_init_bigint(&const_val->data.x_bigfloat, &other_val->data.x_bigint); + } else { + zig_unreachable(); } + const_val->special = ConstValSpecialStatic; + break; case CastOpFloatToInt: float_init_bigint(&const_val->data.x_bigint, other_val); if (new_type->id == ZigTypeIdInt) { diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index 8717c8e619..77cdacc307 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -827,3 +827,12 @@ test "peer type resolve array pointer and unknown pointer" { comptime expect(@TypeOf(&const_array, const_ptr) == [*]const u8); comptime expect(@TypeOf(const_ptr, &const_array) == [*]const u8); } + +test "comptime float casts" { + const a = @intToFloat(comptime_float, 1); + expect(a == 1); + expect(@TypeOf(a) == comptime_float); + const b = @floatToInt(comptime_int, 2); + expect(b == 2); + expect(@TypeOf(b) == comptime_int); +} From 9f496c077766172465a065eafba56dd5280021a6 Mon Sep 17 00:00:00 2001 From: Greg Anders Date: Mon, 11 May 2020 19:36:41 -0600 Subject: [PATCH 52/74] Add helper functions and docstrings to ascii.zig * Add an upper case variant of `allocLowerString` * Add case-sensitive variants of `eqlIgnoreCase`, `indexOfIgnoreCase`, and `indexOfIgnoreCasePos` * Add and update docstrings on functions --- lib/std/ascii.zig | 71 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig index 8bd959b46d..37cb1e461c 100644 --- a/lib/std/ascii.zig +++ b/lib/std/ascii.zig @@ -227,6 +227,8 @@ test "ascii character classes" { testing.expect(isSpace(' ')); } +/// Allocates a lower case copy of `ascii_string`. +/// Caller owns returned string and must free with `allocator`. pub fn allocLowerString(allocator: *std.mem.Allocator, ascii_string: []const u8) ![]u8 { const result = try allocator.alloc(u8, ascii_string.len); for (result) |*c, i| { @@ -241,6 +243,23 @@ test "allocLowerString" { std.testing.expect(std.mem.eql(u8, "abcdefghijklmnopqrst0234+💩!", result)); } +/// Allocates an upper case copy of `ascii_string`. +/// Caller owns returned string and must free with `allocator`. +pub fn allocUpperString(allocator: *std.mem.Allocator, ascii_string: []const u8) ![]u8 { + const result = try allocator.alloc(u8, ascii_string.len); + for (result) |*c, i| { + c.* = toUpper(ascii_string[i]); + } + return result; +} + +test "allocUpperString" { + const result = try allocUpperString(std.testing.allocator, "aBcDeFgHiJkLmNOPqrst0234+💩!"); + defer std.testing.allocator.free(result); + std.testing.expect(std.mem.eql(u8, "ABCDEFGHIJKLMNOPQRST0234+💩!", result)); +} + +/// Return `true` if `a` and `b` are equal, case insensitive. pub fn eqlIgnoreCase(a: []const u8, b: []const u8) bool { if (a.len != b.len) return false; for (a) |a_c, i| { @@ -255,20 +274,43 @@ test "eqlIgnoreCase" { std.testing.expect(!eqlIgnoreCase("hElLo!", "helro!")); } -/// Finds `substr` in `container`, starting at `start_index`. -/// TODO boyer-moore algorithm -pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { +/// Return `true` if `a` and `b` are equal, case sensitive. +pub fn eqlMatchCase(a: []const u8, b: []const u8) bool { + if (a.len != b.len) return false; + for (a) |a_c, i| { + if (a_c != b[i]) return false; + } + return true; +} + +test "eqlMatchCase" { + std.testing.expect(!eqlMatchCase("HEl💩Lo!", "hel💩lo!")); + std.testing.expect(eqlMatchCase("Hello! ", "Hello! ")); + std.testing.expect(eqlMatchCase("hElLo!", "hElLo!")); +} + +fn indexOfPos(container: []const u8, start_index: usize, substr: []const u8, comptime case_sensitive: bool) ?usize { if (substr.len > container.len) return null; var i: usize = start_index; const end = container.len - substr.len; while (i <= end) : (i += 1) { - if (eqlIgnoreCase(container[i .. i + substr.len], substr)) return i; + if (case_sensitive) { + if (eqlMatchCase(container[i .. i + substr.len], substr)) return i; + } else { + if (eqlIgnoreCase(container[i .. i + substr.len], substr)) return i; + } } return null; } -/// Finds `substr` in `container`, starting at `start_index`. +/// Finds `substr` in `container`, case insensitive, starting at `start_index`. +/// TODO boyer-moore algorithm +pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { + return indexOfPos(container, start_index, substr, false); +} + +/// Finds `substr` in `container`, case insensitive, starting at index 0. pub fn indexOfIgnoreCase(container: []const u8, substr: []const u8) ?usize { return indexOfIgnoreCasePos(container, 0, substr); } @@ -281,3 +323,22 @@ test "indexOfIgnoreCase" { std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0); } + +/// Finds `substr` in `container`, case sensitive, starting at `start_index`. +pub fn indexOfMatchCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { + return indexOfPos(container, start_index, substr, true); +} + +/// Finds `substr` in `container`, case sensitive, starting at index 0. +pub fn indexOfMatchCase(container: []const u8, substr: []const u8) ?usize { + return indexOfMatchCasePos(container, 0, substr); +} + +test "indexOfMatchCase" { + std.testing.expect(indexOfMatchCase("one Two Three Four", "Four").? == 14); + std.testing.expect(indexOfMatchCase("one two three FouR", "fOur") == null); + std.testing.expect(indexOfMatchCase("foO", "foO").? == 0); + std.testing.expect(indexOfMatchCase("foo", "fool") == null); + + std.testing.expect(indexOfMatchCase("FOO foo", "FOO").? == 0); +} From b1ebaba40811a6131152b9fc2eb8fb533e9fe5f3 Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 12 May 2020 15:15:21 +0300 Subject: [PATCH 53/74] std.json properly handle comptime int/float --- lib/std/json.zig | 4 ++-- lib/std/json/write_stream.zig | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 1784f44a4d..c4a5ec75d9 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2194,7 +2194,7 @@ test "write json then parse it" { try jw.emitBool(true); try jw.objectField("int"); - try jw.emitNumber(@as(i32, 1234)); + try jw.emitNumber(1234); try jw.objectField("array"); try jw.beginArray(); @@ -2203,7 +2203,7 @@ test "write json then parse it" { try jw.emitNull(); try jw.arrayElem(); - try jw.emitNumber(@as(f64, 12.34)); + try jw.emitNumber(12.34); try jw.endArray(); diff --git a/lib/std/json/write_stream.zig b/lib/std/json/write_stream.zig index 11f0171996..6dd02a03cf 100644 --- a/lib/std/json/write_stream.zig +++ b/lib/std/json/write_stream.zig @@ -148,7 +148,6 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { self.popState(); } - // TODO better handling of ComptimeInt and ComptimeFloat pub fn emitNumber( self: *Self, /// An integer, float, or `std.math.BigInt`. Emitted as a bare number if it fits losslessly @@ -169,8 +168,11 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { return; } }, - .Float => if (@floatCast(f64, value) == value) { - try self.stream.print("{}", .{value}); + .ComptimeInt => { + return self.emitNumber(@as(std.math.IntFittingRange(value, value), value)); + }, + .Float, .ComptimeFloat => if (@floatCast(f64, value) == value) { + try self.stream.print("{}", .{@floatCast(f64, value)}); self.popState(); return; }, From c6420820b0aa5df8db801c9511305b009c8920e9 Mon Sep 17 00:00:00 2001 From: Greg Anders Date: Tue, 12 May 2020 07:14:50 -0600 Subject: [PATCH 54/74] Remove redundant ASCII functions The `matchCase` variants are simply duplicates of the `eql` and `indexOf` functions found in std.mem. --- lib/std/ascii.zig | 54 ++++++----------------------------------------- 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/lib/std/ascii.zig b/lib/std/ascii.zig index 37cb1e461c..102be18bec 100644 --- a/lib/std/ascii.zig +++ b/lib/std/ascii.zig @@ -259,7 +259,7 @@ test "allocUpperString" { std.testing.expect(std.mem.eql(u8, "ABCDEFGHIJKLMNOPQRST0234+💩!", result)); } -/// Return `true` if `a` and `b` are equal, case insensitive. +/// Compares strings `a` and `b` case insensitively and returns whether they are equal. pub fn eqlIgnoreCase(a: []const u8, b: []const u8) bool { if (a.len != b.len) return false; for (a) |a_c, i| { @@ -274,43 +274,20 @@ test "eqlIgnoreCase" { std.testing.expect(!eqlIgnoreCase("hElLo!", "helro!")); } -/// Return `true` if `a` and `b` are equal, case sensitive. -pub fn eqlMatchCase(a: []const u8, b: []const u8) bool { - if (a.len != b.len) return false; - for (a) |a_c, i| { - if (a_c != b[i]) return false; - } - return true; -} - -test "eqlMatchCase" { - std.testing.expect(!eqlMatchCase("HEl💩Lo!", "hel💩lo!")); - std.testing.expect(eqlMatchCase("Hello! ", "Hello! ")); - std.testing.expect(eqlMatchCase("hElLo!", "hElLo!")); -} - -fn indexOfPos(container: []const u8, start_index: usize, substr: []const u8, comptime case_sensitive: bool) ?usize { +/// Finds `substr` in `container`, ignoring case, starting at `start_index`. +/// TODO boyer-moore algorithm +pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { if (substr.len > container.len) return null; var i: usize = start_index; const end = container.len - substr.len; while (i <= end) : (i += 1) { - if (case_sensitive) { - if (eqlMatchCase(container[i .. i + substr.len], substr)) return i; - } else { - if (eqlIgnoreCase(container[i .. i + substr.len], substr)) return i; - } + if (eqlIgnoreCase(container[i .. i + substr.len], substr)) return i; } return null; } -/// Finds `substr` in `container`, case insensitive, starting at `start_index`. -/// TODO boyer-moore algorithm -pub fn indexOfIgnoreCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { - return indexOfPos(container, start_index, substr, false); -} - -/// Finds `substr` in `container`, case insensitive, starting at index 0. +/// Finds `substr` in `container`, ignoring case, starting at index 0. pub fn indexOfIgnoreCase(container: []const u8, substr: []const u8) ?usize { return indexOfIgnoreCasePos(container, 0, substr); } @@ -323,22 +300,3 @@ test "indexOfIgnoreCase" { std.testing.expect(indexOfIgnoreCase("FOO foo", "fOo").? == 0); } - -/// Finds `substr` in `container`, case sensitive, starting at `start_index`. -pub fn indexOfMatchCasePos(container: []const u8, start_index: usize, substr: []const u8) ?usize { - return indexOfPos(container, start_index, substr, true); -} - -/// Finds `substr` in `container`, case sensitive, starting at index 0. -pub fn indexOfMatchCase(container: []const u8, substr: []const u8) ?usize { - return indexOfMatchCasePos(container, 0, substr); -} - -test "indexOfMatchCase" { - std.testing.expect(indexOfMatchCase("one Two Three Four", "Four").? == 14); - std.testing.expect(indexOfMatchCase("one two three FouR", "fOur") == null); - std.testing.expect(indexOfMatchCase("foO", "foO").? == 0); - std.testing.expect(indexOfMatchCase("foo", "fool") == null); - - std.testing.expect(indexOfMatchCase("FOO foo", "FOO").? == 0); -} From fa57463bb9c09ee1e50012d7e50d120e1599fb81 Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 12 May 2020 21:44:08 +0300 Subject: [PATCH 55/74] make parser testError take a list of expected errors --- lib/std/zig/parser_test.zig | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index b98e8c69c3..749fd1e832 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -19,7 +19,9 @@ test "zig fmt: decl between fields" { \\ const baz1 = 2; \\ b: usize, \\}; - ); + , &[_]Error{ + .DeclBetweenFields, + }); } test "zig fmt: errdefer with payload" { @@ -2828,7 +2830,9 @@ test "zig fmt: extern without container keyword returns error" { try testError( \\const container = extern {}; \\ - ); + , &[_]Error{ + .ExpectedExpr, + }); } test "zig fmt: integer literals with underscore separators" { @@ -3030,9 +3034,17 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void { fn testCanonical(source: []const u8) !void { return testTransform(source, source); } -fn testError(source: []const u8) !void { + +const Error = @TagType(std.zig.ast.Error); + +fn testError(source: []const u8, expected_errors: []const Error) !void { const tree = try std.zig.parse(std.testing.allocator, source); defer tree.deinit(); - std.testing.expect(tree.errors.len != 0); + std.testing.expect(tree.errors.len == expected_errors.len); + for (expected_errors) |expected, i| { + const err = tree.errors.at(i); + + std.testing.expect(expected == err.*); + } } From df22c7dfef7312474865c868a633c8e9bbaa63fa Mon Sep 17 00:00:00 2001 From: Vexu Date: Tue, 12 May 2020 22:37:39 +0300 Subject: [PATCH 56/74] std.zig attempt to continue parsing on error --- lib/std/zig/parse.zig | 99 ++++++++++++++++++++++++++++--------- lib/std/zig/parser_test.zig | 10 ++++ 2 files changed, 86 insertions(+), 23 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 031fd9c160..eec1765002 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -48,31 +48,21 @@ pub fn parse(allocator: *Allocator, source: []const u8) Allocator.Error!*Tree { while (it.peek().?.id == .LineComment) _ = it.next(); - tree.root_node = parseRoot(arena, &it, tree) catch |err| blk: { - switch (err) { - error.ParseError => { - assert(tree.errors.len != 0); - break :blk undefined; - }, - error.OutOfMemory => { - return error.OutOfMemory; - }, - } - }; + tree.root_node = try parseRoot(arena, &it, tree); return tree; } /// Root <- skip ContainerMembers eof -fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Root { +fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!*Node.Root { const node = try arena.create(Node.Root); node.* = .{ .decls = try parseContainerMembers(arena, it, tree), - .eof_token = eatToken(it, .Eof) orelse { + .eof_token = eatToken(it, .Eof) orelse blk: { try tree.errors.push(.{ .ExpectedContainerMembers = .{ .token = it.index }, }); - return error.ParseError; + break :blk undefined; }, }; return node; @@ -85,7 +75,7 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!*Node.Roo /// / KEYWORD_pub? ContainerField COMMA ContainerMembers /// / KEYWORD_pub? ContainerField /// / -fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Root.DeclList { +fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!Node.Root.DeclList { var list = Node.Root.DeclList.init(arena); var field_state: union(enum) { @@ -108,7 +98,13 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No const doc_comments = try parseDocComment(arena, it, tree); - if (try parseTestDecl(arena, it, tree)) |node| { + if (parseTestDecl(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + findEndOfBlock(it); + continue; + }, + }) |node| { if (field_state == .seen) { field_state = .{ .end = node.firstToken() }; } @@ -117,7 +113,13 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No continue; } - if (try parseTopLevelComptime(arena, it, tree)) |node| { + if (parseTopLevelComptime(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + findEndOfBlock(it); + continue; + }, + }) |node| { if (field_state == .seen) { field_state = .{ .end = node.firstToken() }; } @@ -128,7 +130,15 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No const visib_token = eatToken(it, .Keyword_pub); - if (try parseTopLevelDecl(arena, it, tree)) |node| { + if (parseTopLevelDecl(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // attempt to recover by finding a semicolon + // TODO if this was a function with a body we should use findEndOfBlock + findToken(it, .Semicolon); + continue; + }, + }) |node| { if (field_state == .seen) { field_state = .{ .end = visib_token orelse node.firstToken() }; } @@ -163,10 +173,17 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No try tree.errors.push(.{ .ExpectedPubItem = .{ .token = it.index }, }); - return error.ParseError; + // ignore this pub } - if (try parseContainerField(arena, it, tree)) |node| { + if (parseContainerField(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // attempt to recover by finding a comma + findToken(it, .Comma); + continue; + }, + }) |node| { switch (field_state) { .none => field_state = .seen, .err, .seen => {}, @@ -200,8 +217,39 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !No return list; } +/// Attempts to find a closing brace, assumes the opening brace was found. +fn findEndOfBlock(it: *TokenIterator) void { + var count: u32 = 1; + while (it.next()) |tok| switch (tok.id) { + .LBrace => count += 1, + .RBrace => { + count -= 1; + if (count == 0) return; + }, + else => {}, + }; +} + +/// Attempts to find `wanted` token, keeps track of parentheses. +fn findToken(it: *TokenIterator, wanted: Token.Id) void { + var count: u32 = 0; + while (it.next()) |tok| switch (tok.id) { + .LParen, .LBracket, .LBrace => count += 1, + .RParen, .RBracket, .RBrace => { + if (count == 0) { + _ = it.prev(); + return; + } + count -= 1; + }, + else => { + if (tok.id == wanted and count == 0) return; + }, + }; +} + /// Eat a multiline container doc comment -fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { +fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!?*Node { var lines = Node.DocComment.LineList.init(arena); while (eatToken(it, .ContainerDocComment)) |line| { try lines.push(line); @@ -687,8 +735,13 @@ fn parseLoopStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Nod node.cast(Node.While).?.inline_token = inline_token; return node; } + if (inline_token == null) return null; - return null; + // If we've seen "inline", there should have been a "for" or "while" + try tree.errors.push(.{ + .ExpectedInlinable = .{ .token = it.index }, + }); + return error.ParseError; } /// ForStatement @@ -2925,7 +2978,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D } /// Eat a single-line doc comment on the same line as another node -fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) !?*Node.DocComment { +fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) Allocator.Error!?*Node.DocComment { const comment_token = eatToken(it, .DocComment) orelse return null; if (tree.tokensOnSameLine(after_token, comment_token)) { const node = try arena.create(Node.DocComment); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 749fd1e832..a925aacc0b 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,3 +1,13 @@ +test "zig fmt: fault tolerant parsing" { + try testError( + \\test "" {inline} + \\test "" {inline} + , &[_]Error{ + .ExpectedInlinable, + .ExpectedInlinable, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, From 706311cad9feff5d8bdf70c6775813f096ea1a85 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 12 May 2020 19:11:05 -0700 Subject: [PATCH 57/74] Fix comment typo RFC8529 -> RFC8259 Ref: https://tools.ietf.org/html/rfc8259 --- lib/std/json.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 74f384946b..fc205d2279 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -136,7 +136,7 @@ pub const Token = union(enum) { /// they are encountered. No copies or allocations are performed during parsing and the entire /// parsing state requires ~40-50 bytes of stack space. /// -/// Conforms strictly to RFC8529. +/// Conforms strictly to RFC8259. /// /// For a non-byte based wrapper, consider using TokenStream instead. pub const StreamingParser = struct { From 91358f3092fb2004bb46572d44a0e377ed400565 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 16:51:23 +0300 Subject: [PATCH 58/74] continue parsing on extra qualifier errors --- lib/std/zig/parse.zig | 53 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index eec1765002..586af02194 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -226,6 +226,10 @@ fn findEndOfBlock(it: *TokenIterator) void { count -= 1; if (count == 0) return; }, + .Eof => { + _ = it.prev(); + return; + }, else => {}, }; } @@ -242,8 +246,12 @@ fn findToken(it: *TokenIterator, wanted: Token.Id) void { } count -= 1; }, + .Eof => { + _ = it.prev(); + return; + }, else => { - if (tok.id == wanted and count == 0) return; + if (tok.id == wanted and count == 0) return; }, }; } @@ -2324,7 +2332,7 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node const node = try arena.create(Node.AnyFrameType); node.* = .{ .anyframe_token = token, - .result = Node.AnyFrameType.Result{ + .result = .{ .arrow_token = arrow, .return_type = undefined, // set by caller }, @@ -2365,6 +2373,13 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node } else null; _ = try expectToken(it, tree, .RParen); + if (ptr_info.align_info != null) { + try tree.errors.push(.{ + .ExtraAlignQualifier = .{ .token = it.index - 1 }, + }); + continue; + } + ptr_info.align_info = Node.PrefixOp.PtrInfo.Align{ .node = expr_node, .bit_range = bit_range, @@ -2373,14 +2388,32 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node continue; } if (eatToken(it, .Keyword_const)) |const_token| { + if (ptr_info.const_token != null) { + try tree.errors.push(.{ + .ExtraConstQualifier = .{ .token = it.index - 1 }, + }); + continue; + } ptr_info.const_token = const_token; continue; } if (eatToken(it, .Keyword_volatile)) |volatile_token| { + if (ptr_info.volatile_token != null) { + try tree.errors.push(.{ + .ExtraVolatileQualifier = .{ .token = it.index - 1 }, + }); + continue; + } ptr_info.volatile_token = volatile_token; continue; } if (eatToken(it, .Keyword_allowzero)) |allowzero_token| { + if (ptr_info.allowzero_token != null) { + try tree.errors.push(.{ + .ExtraAllowZeroQualifier = .{ .token = it.index - 1 }, + }); + continue; + } ptr_info.allowzero_token = allowzero_token; continue; } @@ -2399,9 +2432,9 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node if (try parseByteAlign(arena, it, tree)) |align_expr| { if (slice_type.align_info != null) { try tree.errors.push(.{ - .ExtraAlignQualifier = .{ .token = it.index }, + .ExtraAlignQualifier = .{ .token = it.index - 1 }, }); - return error.ParseError; + continue; } slice_type.align_info = Node.PrefixOp.PtrInfo.Align{ .node = align_expr, @@ -2412,9 +2445,9 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node if (eatToken(it, .Keyword_const)) |const_token| { if (slice_type.const_token != null) { try tree.errors.push(.{ - .ExtraConstQualifier = .{ .token = it.index }, + .ExtraConstQualifier = .{ .token = it.index - 1 }, }); - return error.ParseError; + continue; } slice_type.const_token = const_token; continue; @@ -2422,9 +2455,9 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node if (eatToken(it, .Keyword_volatile)) |volatile_token| { if (slice_type.volatile_token != null) { try tree.errors.push(.{ - .ExtraVolatileQualifier = .{ .token = it.index }, + .ExtraVolatileQualifier = .{ .token = it.index - 1 }, }); - return error.ParseError; + continue; } slice_type.volatile_token = volatile_token; continue; @@ -2432,9 +2465,9 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node if (eatToken(it, .Keyword_allowzero)) |allowzero_token| { if (slice_type.allowzero_token != null) { try tree.errors.push(.{ - .ExtraAllowZeroQualifier = .{ .token = it.index }, + .ExtraAllowZeroQualifier = .{ .token = it.index - 1 }, }); - return error.ParseError; + continue; } slice_type.allowzero_token = allowzero_token; continue; From be392777b763028a02866342b12915a1e69ebdf1 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 17:21:27 +0300 Subject: [PATCH 59/74] continue parsing after missing commas and invalid statements --- lib/std/zig/ast.zig | 4 ++++ lib/std/zig/parse.zig | 28 ++++++++++++++++++++++++++-- lib/std/zig/parser_test.zig | 24 ++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 8dec2de15c..dd9abe61ac 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -165,6 +165,7 @@ pub const Error = union(enum) { ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap, ExpectedSuffixOp: ExpectedSuffixOp, DeclBetweenFields: DeclBetweenFields, + MissingComma: MissingComma, pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { switch (self.*) { @@ -213,6 +214,7 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), .ExpectedSuffixOp => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream), + .MissingComma => |*x| return x.render(tokens, stream), } } @@ -263,6 +265,7 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |x| return x.token, .ExpectedSuffixOp => |x| return x.token, .DeclBetweenFields => |x| return x.token, + .MissingComma => |x| return x.token, } } @@ -308,6 +311,7 @@ pub const Error = union(enum) { pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); + pub const MissingComma = SimpleError("Expected comma between items"); pub const ExpectedCall = struct { node: *Node, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 586af02194..ad4f5e1242 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1083,7 +1083,14 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { var statements = Node.Block.StatementList.init(arena); while (true) { - const statement = (try parseStatement(arena, it, tree)) orelse break; + const statement = (parseStatement(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // try to skip to the next statement + findToken(it, .Semicolon); + continue; + }, + }) orelse break; try statements.push(statement); } @@ -2816,7 +2823,24 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) { var list = L.init(arena); while (try nodeParseFn(arena, it, tree)) |node| { try list.push(node); - if (eatToken(it, .Comma) == null) break; + + const token = nextToken(it); + switch (token.ptr.id) { + .Comma => {}, + // all possible delimiters + .Colon, .RParen, .RBrace, .RBracket => { + putBackToken(it, token.index); + break; + }, + else => { + // this is likely just a missing comma, + // continue parsing this list and give an error + try tree.errors.push(.{ + .MissingComma = .{ .token = token.index }, + }); + putBackToken(it, token.index); + }, + } } return list; } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index a925aacc0b..2c8b53f7f0 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -6,6 +6,30 @@ test "zig fmt: fault tolerant parsing" { .ExpectedInlinable, .ExpectedInlinable, }); + try testError( + \\test "" { + \\ foo + +; + \\ inline; + \\} + , &[_]Error{ + .InvalidToken, + .ExpectedInlinable, + }); + try testError( + \\test "" { + \\ switch (foo) { + \\ 2 => {} + \\ 3 => {} + \\ else => { + \\ inline; + \\ } + \\ } + \\} + , &[_]Error{ + .MissingComma, + .MissingComma, + .ExpectedInlinable, + }); } test "zig fmt: top-level fields" { From cefc04348e79f85118ad3c7b7fd15a4a5d635d50 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 17:36:06 +0300 Subject: [PATCH 60/74] continue parsing on invalid and token --- lib/std/zig/ast.zig | 7 ++++--- lib/std/zig/parse.zig | 25 +++++++++++++++---------- lib/std/zig/parser_test.zig | 5 +++-- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index dd9abe61ac..339927d636 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -166,6 +166,7 @@ pub const Error = union(enum) { ExpectedSuffixOp: ExpectedSuffixOp, DeclBetweenFields: DeclBetweenFields, MissingComma: MissingComma, + InvalidAnd: InvalidAnd, pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { switch (self.*) { @@ -215,6 +216,7 @@ pub const Error = union(enum) { .ExpectedSuffixOp => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream), .MissingComma => |*x| return x.render(tokens, stream), + .InvalidAnd => |*x| return x.render(tokens, stream), } } @@ -266,6 +268,7 @@ pub const Error = union(enum) { .ExpectedSuffixOp => |x| return x.token, .DeclBetweenFields => |x| return x.token, .MissingComma => |x| return x.token, + .InvalidAnd => |x| return x.token, } } @@ -312,6 +315,7 @@ pub const Error = union(enum) { pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); pub const MissingComma = SimpleError("Expected comma between items"); + pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); pub const ExpectedCall = struct { node: *Node, @@ -339,9 +343,6 @@ pub const Error = union(enum) { pub fn render(self: *const ExpectedToken, tokens: *Tree.TokenList, stream: var) !void { const found_token = tokens.at(self.token); switch (found_token.id) { - .Invalid_ampersands => { - return stream.print("`&&` is invalid. Note that `and` is boolean AND.", .{}); - }, .Invalid => { return stream.print("expected '{}', found invalid bytes", .{self.expected_id.symbol()}); }, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index ad4f5e1242..af501cd8a4 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -2824,21 +2824,16 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) { while (try nodeParseFn(arena, it, tree)) |node| { try list.push(node); - const token = nextToken(it); - switch (token.ptr.id) { - .Comma => {}, + switch (it.peek().?.id) { + .Comma => _ = nextToken(it), // all possible delimiters - .Colon, .RParen, .RBrace, .RBracket => { - putBackToken(it, token.index); - break; - }, + .Colon, .RParen, .RBrace, .RBracket => break, else => { // this is likely just a missing comma, // continue parsing this list and give an error try tree.errors.push(.{ - .MissingComma = .{ .token = token.index }, + .MissingComma = .{ .token = it.index }, }); - putBackToken(it, token.index); }, } } @@ -2850,7 +2845,17 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) { fn SimpleBinOpParseFn(comptime token: Token.Id, comptime op: Node.InfixOp.Op) NodeParseFn { return struct { pub fn parse(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { - const op_token = eatToken(it, token) orelse return null; + const op_token = if (token == .Keyword_and) switch (it.peek().?.id) { + .Keyword_and => nextToken(it).index, + .Invalid_ampersands => blk: { + try tree.errors.push(.{ + .InvalidAnd = .{ .token = it.index }, + }); + break :blk nextToken(it).index; + }, + else => return null, + } else eatToken(it, token) orelse return null; + const node = try arena.create(Node.InfixOp); node.* = .{ .op_token = op_token, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 2c8b53f7f0..b92ce1ea23 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -21,14 +21,15 @@ test "zig fmt: fault tolerant parsing" { \\ 2 => {} \\ 3 => {} \\ else => { - \\ inline; + \\ foo && bar +; \\ } \\ } \\} , &[_]Error{ .MissingComma, .MissingComma, - .ExpectedInlinable, + .InvalidAnd, + .InvalidToken, }); } From afab095b6115e189ea2c5e0947a21e55a82c9f99 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 17:53:15 +0300 Subject: [PATCH 61/74] translate-c remove error set from `checkForBuiltinTypedef` --- src-self-hosted/translate_c.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 7da6f402af..0b4854dcdc 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -668,7 +668,7 @@ fn transTypeDefAsBuiltin(c: *Context, typedef_decl: *const ZigClangTypedefNameDe return transCreateNodeIdentifier(c, builtin_name); } -fn checkForBuiltinTypedef(checked_name: []const u8) !?[]const u8 { +fn checkForBuiltinTypedef(checked_name: []const u8) ?[]const u8 { const table = [_][2][]const u8{ .{ "uint8_t", "u8" }, .{ "int8_t", "i8" }, @@ -703,7 +703,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; - if (try checkForBuiltinTypedef(checked_name)) |builtin| { + if (checkForBuiltinTypedef(checked_name)) |builtin| { return transTypeDefAsBuiltin(c, typedef_decl, builtin); } @@ -1411,7 +1411,7 @@ fn transDeclStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangDeclStmt) const underlying_type = ZigClangQualType_getTypePtr(underlying_qual); const mangled_name = try block_scope.makeMangledName(c, name); - if (try checkForBuiltinTypedef(name)) |builtin| { + if (checkForBuiltinTypedef(name)) |builtin| { try block_scope.variables.push(.{ .alias = builtin, .name = mangled_name, From 2589f7207baef686dff969ccf2bd596a16b5012e Mon Sep 17 00:00:00 2001 From: DrDeano Date: Wed, 13 May 2020 16:21:15 +0100 Subject: [PATCH 62/74] Make StackIterator next public --- lib/std/debug.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index d999de6a17..3e52770932 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -357,7 +357,7 @@ pub const StackIterator = struct { else 0; - fn next(self: *StackIterator) ?usize { + pub fn next(self: *StackIterator) ?usize { var address = self.next_internal() orelse return null; if (self.first_address) |first_address| { From 76681e6b9689c4df78b6451da1aa857dc08a84d2 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 18:38:03 +0300 Subject: [PATCH 63/74] Make PriorityQueue.Iterator public The `iterator` function was already public but these seem to have been forgotten. --- lib/std/priority_queue.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std/priority_queue.zig b/lib/std/priority_queue.zig index e726a07a88..dfd2379da2 100644 --- a/lib/std/priority_queue.zig +++ b/lib/std/priority_queue.zig @@ -185,18 +185,18 @@ pub fn PriorityQueue(comptime T: type) type { self.len = new_len; } - const Iterator = struct { + pub const Iterator = struct { queue: *PriorityQueue(T), count: usize, - fn next(it: *Iterator) ?T { + pub fn next(it: *Iterator) ?T { if (it.count > it.queue.len - 1) return null; const out = it.count; it.count += 1; return it.queue.items[out]; } - fn reset(it: *Iterator) void { + pub fn reset(it: *Iterator) void { it.count = 0; } }; From 23c5ff94e9dda07694762fcc829dbac006bb00a1 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 20:42:18 +0300 Subject: [PATCH 64/74] improve recovery on top level declarations --- lib/std/zig/ast.zig | 2 + lib/std/zig/parse.zig | 157 +++++++++++++++++++++--------------- lib/std/zig/parser_test.zig | 31 ++++++- lib/std/zig/render.zig | 6 +- 4 files changed, 127 insertions(+), 69 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 339927d636..afb7fce23e 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -893,6 +893,7 @@ pub const Node = struct { pub const ReturnType = union(enum) { Explicit: *Node, InferErrorSet: *Node, + Invalid, }; pub fn iterate(self: *FnProto, index: usize) ?*Node { @@ -942,6 +943,7 @@ pub const Node = struct { if (self.body_node) |body_node| return body_node.lastToken(); switch (self.return_type) { .Explicit, .InferErrorSet => |node| return node.lastToken(), + .Invalid => unreachable, } } }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index af501cd8a4..6052d92d6a 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -130,15 +130,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All const visib_token = eatToken(it, .Keyword_pub); - if (parseTopLevelDecl(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - // attempt to recover by finding a semicolon - // TODO if this was a function with a body we should use findEndOfBlock - findToken(it, .Semicolon); - continue; - }, - }) |node| { + if (try parseTopLevelDecl(arena, it, tree)) |node| { if (field_state == .seen) { field_state = .{ .end = visib_token orelse node.firstToken() }; } @@ -217,43 +209,49 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All return list; } -/// Attempts to find a closing brace, assumes the opening brace was found. +/// Attempts to find a closing brace. fn findEndOfBlock(it: *TokenIterator) void { - var count: u32 = 1; - while (it.next()) |tok| switch (tok.id) { - .LBrace => count += 1, - .RBrace => { - count -= 1; - if (count == 0) return; - }, - .Eof => { - _ = it.prev(); - return; - }, - else => {}, - }; + var count: u32 = 0; + while (true) { + const tok = nextToken(it); + switch (tok.ptr.id) { + .LBrace => count += 1, + .RBrace => { + if (count <= 1) return; + count -= 1; + }, + .Eof => { + putBackToken(it, tok.index); + return; + }, + else => {}, + } + } } /// Attempts to find `wanted` token, keeps track of parentheses. fn findToken(it: *TokenIterator, wanted: Token.Id) void { var count: u32 = 0; - while (it.next()) |tok| switch (tok.id) { - .LParen, .LBracket, .LBrace => count += 1, - .RParen, .RBracket, .RBrace => { - if (count == 0) { - _ = it.prev(); + while (true) { + const tok = nextToken(it); + switch (tok.ptr.id) { + .LParen, .LBracket, .LBrace => count += 1, + .RParen, .RBracket, .RBrace => { + if (count == 0) { + putBackToken(it, tok.index); + return; + } + count -= 1; + }, + .Eof => { + putBackToken(it, tok.index); return; - } - count -= 1; - }, - .Eof => { - _ = it.prev(); - return; - }, - else => { - if (tok.id == wanted and count == 0) return; - }, - }; + }, + else => { + if (tok.ptr.id == wanted and count == 0) return; + }, + } + } } /// Eat a multiline container doc comment @@ -317,7 +315,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl /// / KEYWORD_usingnamespace Expr SEMICOLON -fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { +fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!?*Node { var lib_name: ?*Node = null; const extern_export_inline_token = blk: { if (eatToken(it, .Keyword_export)) |token| break :blk token; @@ -330,12 +328,26 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node break :blk null; }; - if (try parseFnProto(arena, it, tree)) |node| { + if (parseFnProto(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // this fn will likely have a body so we + // use findEndOfBlock instead of findToken. + findEndOfBlock(it); + return null; + }, + }) |node| { const fn_node = node.cast(Node.FnProto).?; fn_node.*.extern_export_inline_token = extern_export_inline_token; fn_node.*.lib_name = lib_name; if (eatToken(it, .Semicolon)) |_| return node; - if (try parseBlock(arena, it, tree)) |body_node| { + if (parseBlock(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + // since parseBlock only return error.ParseError on + // a missing '}' we can assume this function was + // supposed to end here. + error.ParseError => null, + }) |body_node| { fn_node.body_node = body_node; return node; } @@ -356,7 +368,14 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node const thread_local_token = eatToken(it, .Keyword_threadlocal); - if (try parseVarDecl(arena, it, tree)) |node| { + if (parseVarDecl(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // try to skip to next decl + findToken(it, .Semicolon); + return null; + }, + }) |node| { var var_decl = node.cast(Node.VarDecl).?; var_decl.*.thread_local_token = thread_local_token; var_decl.*.comptime_token = null; @@ -369,7 +388,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node try tree.errors.push(.{ .ExpectedVarDecl = .{ .token = it.index }, }); - return error.ParseError; + // ignore this, try to find next decl by skipping the next block + findEndOfBlock(it); } if (extern_export_inline_token) |token| { @@ -379,16 +399,14 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node return null; } - const use_node = (try parseUse(arena, it, tree)) orelse return null; - const expr_node = try expectNode(arena, it, tree, parseExpr, .{ - .ExpectedExpr = .{ .token = it.index }, - }); - const semicolon_token = try expectToken(it, tree, .Semicolon); - const use_node_raw = use_node.cast(Node.Use).?; - use_node_raw.*.expr = expr_node; - use_node_raw.*.semicolon_token = semicolon_token; - - return use_node; + return parseUse(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // try to skip to next decl + findToken(it, .Semicolon); + return null; + }, + }; } /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) @@ -422,18 +440,23 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { const exclamation_token = eatToken(it, .Bang); const return_type_expr = (try parseVarType(arena, it, tree)) orelse - try expectNode(arena, it, tree, parseTypeExpr, .{ - .ExpectedReturnType = .{ .token = it.index }, - }); + (try parseTypeExpr(arena, it, tree)) orelse blk: { + try tree.errors.push(.{ + .ExpectedReturnType = .{ .token = it.index }, + }); + // most likely the user forgot to specify the return type. + // Mark return type as invalid and try to continue. + break :blk null; + }; - const return_type: Node.FnProto.ReturnType = if (exclamation_token != null) - .{ - .InferErrorSet = return_type_expr, - } + // TODO https://github.com/ziglang/zig/issues/3750 + const R = Node.FnProto.ReturnType; + const return_type = if (return_type_expr == null) + R{ .Invalid = {} } + else if (exclamation_token != null) + R{ .InferErrorSet = return_type_expr.? } else - .{ - .Explicit = return_type_expr, - }; + R{ .Explicit = return_type_expr.? }; const var_args_token = if (params.len > 0) params.at(params.len - 1).*.cast(Node.ParamDecl).?.var_args_token @@ -2992,8 +3015,10 @@ fn parseUse(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { .doc_comments = null, .visib_token = null, .use_token = token, - .expr = undefined, // set by caller - .semicolon_token = undefined, // set by caller + .expr = try expectNode(arena, it, tree, parseExpr, .{ + .ExpectedExpr = .{ .token = it.index }, + }), + .semicolon_token = try expectToken(it, tree, .Semicolon), }; return &node.base; } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index b92ce1ea23..e3bc20bd10 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -1,4 +1,4 @@ -test "zig fmt: fault tolerant parsing" { +test "recovery: top level" { try testError( \\test "" {inline} \\test "" {inline} @@ -6,6 +6,9 @@ test "zig fmt: fault tolerant parsing" { .ExpectedInlinable, .ExpectedInlinable, }); +} + +test "recovery: block statements" { try testError( \\test "" { \\ foo + +; @@ -15,6 +18,9 @@ test "zig fmt: fault tolerant parsing" { .InvalidToken, .ExpectedInlinable, }); +} + +test "recovery: missing comma" { try testError( \\test "" { \\ switch (foo) { @@ -33,6 +39,29 @@ test "zig fmt: fault tolerant parsing" { }); } +test "recovery: extra qualifier" { + try testError( + \\const a: *const const u8; + \\test "" + , &[_]Error{ + .ExtraConstQualifier, + .ExpectedLBrace, + }); +} + +test "recovery: missing return type" { + try testError( + \\fn foo() { + \\ a && b; + \\} + \\test "" + , &[_]Error{ + .ExpectedReturnType, + .InvalidAnd, + .ExpectedLBrace, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index bcdc08d43a..64f2f77f6c 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -1444,6 +1444,7 @@ fn renderExpression( else switch (fn_proto.return_type) { .Explicit => |node| node.firstToken(), .InferErrorSet => |node| tree.prevToken(node.firstToken()), + .Invalid => unreachable, }); assert(tree.tokens.at(rparen).id == .RParen); @@ -1518,13 +1519,14 @@ fn renderExpression( } switch (fn_proto.return_type) { - ast.Node.FnProto.ReturnType.Explicit => |node| { + .Explicit => |node| { return renderExpression(allocator, stream, tree, indent, start_col, node, space); }, - ast.Node.FnProto.ReturnType.InferErrorSet => |node| { + .InferErrorSet => |node| { try renderToken(tree, stream, tree.prevToken(node.firstToken()), indent, start_col, Space.None); // ! return renderExpression(allocator, stream, tree, indent, start_col, node, space); }, + .Invalid => unreachable, } }, From 2296906e2ad54c387b4b19784148c47a26969cdc Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 23:08:42 +0300 Subject: [PATCH 65/74] modernize std.zig.tokenizer --- lib/std/zig/tokenizer.zig | 946 +++++++++++++++++++------------------- 1 file changed, 473 insertions(+), 473 deletions(-) diff --git a/lib/std/zig/tokenizer.zig b/lib/std/zig/tokenizer.zig index 089711871e..160530f459 100644 --- a/lib/std/zig/tokenizer.zig +++ b/lib/std/zig/tokenizer.zig @@ -353,64 +353,64 @@ pub const Tokenizer = struct { } const State = enum { - Start, - Identifier, - Builtin, - StringLiteral, - StringLiteralBackslash, - MultilineStringLiteralLine, - CharLiteral, - CharLiteralBackslash, - CharLiteralHexEscape, - CharLiteralUnicodeEscapeSawU, - CharLiteralUnicodeEscape, - CharLiteralUnicodeInvalid, - CharLiteralUnicode, - CharLiteralEnd, - Backslash, - Equal, - Bang, - Pipe, - Minus, - MinusPercent, - Asterisk, - AsteriskPercent, - Slash, - LineCommentStart, - LineComment, - DocCommentStart, - DocComment, - ContainerDocComment, - Zero, - IntegerLiteralDec, - IntegerLiteralDecNoUnderscore, - IntegerLiteralBin, - IntegerLiteralBinNoUnderscore, - IntegerLiteralOct, - IntegerLiteralOctNoUnderscore, - IntegerLiteralHex, - IntegerLiteralHexNoUnderscore, - NumberDotDec, - NumberDotHex, - FloatFractionDec, - FloatFractionDecNoUnderscore, - FloatFractionHex, - FloatFractionHexNoUnderscore, - FloatExponentUnsigned, - FloatExponentNumber, - FloatExponentNumberNoUnderscore, - Ampersand, - Caret, - Percent, - Plus, - PlusPercent, - AngleBracketLeft, - AngleBracketAngleBracketLeft, - AngleBracketRight, - AngleBracketAngleBracketRight, - Period, - Period2, - SawAtSign, + start, + identifier, + builtin, + string_literal, + string_literal_backslash, + multiline_string_literal_line, + char_literal, + char_literal_backslash, + char_literal_hex_escape, + char_literal_unicode_escape_saw_u, + char_literal_unicode_escape, + char_literal_unicode_invalid, + char_literal_unicode, + char_literal_end, + backslash, + equal, + bang, + pipe, + minus, + minus_percent, + asterisk, + asterisk_percent, + slash, + line_comment_start, + line_comment, + doc_comment_start, + doc_comment, + container_doc_comment, + zero, + int_literal_dec, + int_literal_dec_no_underscore, + int_literal_bin, + int_literal_bin_no_underscore, + int_literal_oct, + int_literal_oct_no_underscore, + int_literal_hex, + int_literal_hex_no_underscore, + num_dot_dec, + num_dot_hex, + float_fraction_dec, + float_fraction_dec_no_underscore, + float_fraction_hex, + float_fraction_hex_no_underscore, + float_exponent_unsigned, + float_exponent_num, + float_exponent_num_no_underscore, + ampersand, + caret, + percent, + plus, + plus_percent, + angle_bracket_left, + angle_bracket_angle_bracket_left, + angle_bracket_right, + angle_bracket_angle_bracket_right, + period, + period_2, + saw_at_sign, }; fn isIdentifierChar(char: u8) bool { @@ -423,9 +423,9 @@ pub const Tokenizer = struct { return token; } const start_index = self.index; - var state = State.Start; + var state: State = .start; var result = Token{ - .id = Token.Id.Eof, + .id = .Eof, .start = self.index, .end = undefined, }; @@ -434,40 +434,40 @@ pub const Tokenizer = struct { while (self.index < self.buffer.len) : (self.index += 1) { const c = self.buffer[self.index]; switch (state) { - State.Start => switch (c) { + .start => switch (c) { ' ', '\n', '\t', '\r' => { result.start = self.index + 1; }, '"' => { - state = State.StringLiteral; - result.id = Token.Id.StringLiteral; + state = .string_literal; + result.id = .StringLiteral; }, '\'' => { - state = State.CharLiteral; + state = .char_literal; }, 'a'...'z', 'A'...'Z', '_' => { - state = State.Identifier; - result.id = Token.Id.Identifier; + state = .identifier; + result.id = .Identifier; }, '@' => { - state = State.SawAtSign; + state = .saw_at_sign; }, '=' => { - state = State.Equal; + state = .equal; }, '!' => { - state = State.Bang; + state = .bang; }, '|' => { - state = State.Pipe; + state = .pipe; }, '(' => { - result.id = Token.Id.LParen; + result.id = .LParen; self.index += 1; break; }, ')' => { - result.id = Token.Id.RParen; + result.id = .RParen; self.index += 1; break; }, @@ -477,213 +477,213 @@ pub const Tokenizer = struct { break; }, ']' => { - result.id = Token.Id.RBracket; + result.id = .RBracket; self.index += 1; break; }, ';' => { - result.id = Token.Id.Semicolon; + result.id = .Semicolon; self.index += 1; break; }, ',' => { - result.id = Token.Id.Comma; + result.id = .Comma; self.index += 1; break; }, '?' => { - result.id = Token.Id.QuestionMark; + result.id = .QuestionMark; self.index += 1; break; }, ':' => { - result.id = Token.Id.Colon; + result.id = .Colon; self.index += 1; break; }, '%' => { - state = State.Percent; + state = .percent; }, '*' => { - state = State.Asterisk; + state = .asterisk; }, '+' => { - state = State.Plus; + state = .plus; }, '<' => { - state = State.AngleBracketLeft; + state = .angle_bracket_left; }, '>' => { - state = State.AngleBracketRight; + state = .angle_bracket_right; }, '^' => { - state = State.Caret; + state = .caret; }, '\\' => { - state = State.Backslash; - result.id = Token.Id.MultilineStringLiteralLine; + state = .backslash; + result.id = .MultilineStringLiteralLine; }, '{' => { - result.id = Token.Id.LBrace; + result.id = .LBrace; self.index += 1; break; }, '}' => { - result.id = Token.Id.RBrace; + result.id = .RBrace; self.index += 1; break; }, '~' => { - result.id = Token.Id.Tilde; + result.id = .Tilde; self.index += 1; break; }, '.' => { - state = State.Period; + state = .period; }, '-' => { - state = State.Minus; + state = .minus; }, '/' => { - state = State.Slash; + state = .slash; }, '&' => { - state = State.Ampersand; + state = .ampersand; }, '0' => { - state = State.Zero; - result.id = Token.Id.IntegerLiteral; + state = .zero; + result.id = .IntegerLiteral; }, '1'...'9' => { - state = State.IntegerLiteralDec; - result.id = Token.Id.IntegerLiteral; + state = .int_literal_dec; + result.id = .IntegerLiteral; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; self.index += 1; break; }, }, - State.SawAtSign => switch (c) { + .saw_at_sign => switch (c) { '"' => { - result.id = Token.Id.Identifier; - state = State.StringLiteral; + result.id = .Identifier; + state = .string_literal; }, else => { // reinterpret as a builtin self.index -= 1; - state = State.Builtin; - result.id = Token.Id.Builtin; + state = .builtin; + result.id = .Builtin; }, }, - State.Ampersand => switch (c) { + .ampersand => switch (c) { '&' => { - result.id = Token.Id.Invalid_ampersands; + result.id = .Invalid_ampersands; self.index += 1; break; }, '=' => { - result.id = Token.Id.AmpersandEqual; + result.id = .AmpersandEqual; self.index += 1; break; }, else => { - result.id = Token.Id.Ampersand; + result.id = .Ampersand; break; }, }, - State.Asterisk => switch (c) { + .asterisk => switch (c) { '=' => { - result.id = Token.Id.AsteriskEqual; + result.id = .AsteriskEqual; self.index += 1; break; }, '*' => { - result.id = Token.Id.AsteriskAsterisk; + result.id = .AsteriskAsterisk; self.index += 1; break; }, '%' => { - state = State.AsteriskPercent; + state = .asterisk_percent; }, else => { - result.id = Token.Id.Asterisk; + result.id = .Asterisk; break; }, }, - State.AsteriskPercent => switch (c) { + .asterisk_percent => switch (c) { '=' => { - result.id = Token.Id.AsteriskPercentEqual; + result.id = .AsteriskPercentEqual; self.index += 1; break; }, else => { - result.id = Token.Id.AsteriskPercent; + result.id = .AsteriskPercent; break; }, }, - State.Percent => switch (c) { + .percent => switch (c) { '=' => { - result.id = Token.Id.PercentEqual; + result.id = .PercentEqual; self.index += 1; break; }, else => { - result.id = Token.Id.Percent; + result.id = .Percent; break; }, }, - State.Plus => switch (c) { + .plus => switch (c) { '=' => { - result.id = Token.Id.PlusEqual; + result.id = .PlusEqual; self.index += 1; break; }, '+' => { - result.id = Token.Id.PlusPlus; + result.id = .PlusPlus; self.index += 1; break; }, '%' => { - state = State.PlusPercent; + state = .plus_percent; }, else => { - result.id = Token.Id.Plus; + result.id = .Plus; break; }, }, - State.PlusPercent => switch (c) { + .plus_percent => switch (c) { '=' => { - result.id = Token.Id.PlusPercentEqual; + result.id = .PlusPercentEqual; self.index += 1; break; }, else => { - result.id = Token.Id.PlusPercent; + result.id = .PlusPercent; break; }, }, - State.Caret => switch (c) { + .caret => switch (c) { '=' => { - result.id = Token.Id.CaretEqual; + result.id = .CaretEqual; self.index += 1; break; }, else => { - result.id = Token.Id.Caret; + result.id = .Caret; break; }, }, - State.Identifier => switch (c) { + .identifier => switch (c) { 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, else => { if (Token.getKeyword(self.buffer[result.start..self.index])) |id| { @@ -692,19 +692,19 @@ pub const Tokenizer = struct { break; }, }, - State.Builtin => switch (c) { + .builtin => switch (c) { 'a'...'z', 'A'...'Z', '_', '0'...'9' => {}, else => break, }, - State.Backslash => switch (c) { + .backslash => switch (c) { '\\' => { - state = State.MultilineStringLiteralLine; + state = .multiline_string_literal_line; }, else => break, }, - State.StringLiteral => switch (c) { + .string_literal => switch (c) { '\\' => { - state = State.StringLiteralBackslash; + state = .string_literal_backslash; }, '"' => { self.index += 1; @@ -714,98 +714,98 @@ pub const Tokenizer = struct { else => self.checkLiteralCharacter(), }, - State.StringLiteralBackslash => switch (c) { + .string_literal_backslash => switch (c) { '\n', '\r' => break, // Look for this error later. else => { - state = State.StringLiteral; + state = .string_literal; }, }, - State.CharLiteral => switch (c) { + .char_literal => switch (c) { '\\' => { - state = State.CharLiteralBackslash; + state = .char_literal_backslash; }, '\'', 0x80...0xbf, 0xf8...0xff => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, 0xc0...0xdf => { // 110xxxxx remaining_code_units = 1; - state = State.CharLiteralUnicode; + state = .char_literal_unicode; }, 0xe0...0xef => { // 1110xxxx remaining_code_units = 2; - state = State.CharLiteralUnicode; + state = .char_literal_unicode; }, 0xf0...0xf7 => { // 11110xxx remaining_code_units = 3; - state = State.CharLiteralUnicode; + state = .char_literal_unicode; }, else => { - state = State.CharLiteralEnd; + state = .char_literal_end; }, }, - State.CharLiteralBackslash => switch (c) { + .char_literal_backslash => switch (c) { '\n' => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, 'x' => { - state = State.CharLiteralHexEscape; + state = .char_literal_hex_escape; seen_escape_digits = 0; }, 'u' => { - state = State.CharLiteralUnicodeEscapeSawU; + state = .char_literal_unicode_escape_saw_u; }, else => { - state = State.CharLiteralEnd; + state = .char_literal_end; }, }, - State.CharLiteralHexEscape => switch (c) { + .char_literal_hex_escape => switch (c) { '0'...'9', 'a'...'f', 'A'...'F' => { seen_escape_digits += 1; if (seen_escape_digits == 2) { - state = State.CharLiteralEnd; + state = .char_literal_end; } }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.CharLiteralUnicodeEscapeSawU => switch (c) { + .char_literal_unicode_escape_saw_u => switch (c) { '{' => { - state = State.CharLiteralUnicodeEscape; + state = .char_literal_unicode_escape; seen_escape_digits = 0; }, else => { - result.id = Token.Id.Invalid; - state = State.CharLiteralUnicodeInvalid; + result.id = .Invalid; + state = .char_literal_unicode_invalid; }, }, - State.CharLiteralUnicodeEscape => switch (c) { + .char_literal_unicode_escape => switch (c) { '0'...'9', 'a'...'f', 'A'...'F' => { seen_escape_digits += 1; }, '}' => { if (seen_escape_digits == 0) { - result.id = Token.Id.Invalid; - state = State.CharLiteralUnicodeInvalid; + result.id = .Invalid; + state = .char_literal_unicode_invalid; } else { - state = State.CharLiteralEnd; + state = .char_literal_end; } }, else => { - result.id = Token.Id.Invalid; - state = State.CharLiteralUnicodeInvalid; + result.id = .Invalid; + state = .char_literal_unicode_invalid; }, }, - State.CharLiteralUnicodeInvalid => switch (c) { + .char_literal_unicode_invalid => switch (c) { // Keep consuming characters until an obvious stopping point. // This consolidates e.g. `u{0ab1Q}` into a single invalid token // instead of creating the tokens `u{0ab1`, `Q`, `}` @@ -813,32 +813,32 @@ pub const Tokenizer = struct { else => break, }, - State.CharLiteralEnd => switch (c) { + .char_literal_end => switch (c) { '\'' => { - result.id = Token.Id.CharLiteral; + result.id = .CharLiteral; self.index += 1; break; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.CharLiteralUnicode => switch (c) { + .char_literal_unicode => switch (c) { 0x80...0xbf => { remaining_code_units -= 1; if (remaining_code_units == 0) { - state = State.CharLiteralEnd; + state = .char_literal_end; } }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.MultilineStringLiteralLine => switch (c) { + .multiline_string_literal_line => switch (c) { '\n' => { self.index += 1; break; @@ -847,449 +847,449 @@ pub const Tokenizer = struct { else => self.checkLiteralCharacter(), }, - State.Bang => switch (c) { + .bang => switch (c) { '=' => { - result.id = Token.Id.BangEqual; + result.id = .BangEqual; self.index += 1; break; }, else => { - result.id = Token.Id.Bang; + result.id = .Bang; break; }, }, - State.Pipe => switch (c) { + .pipe => switch (c) { '=' => { - result.id = Token.Id.PipeEqual; + result.id = .PipeEqual; self.index += 1; break; }, '|' => { - result.id = Token.Id.PipePipe; + result.id = .PipePipe; self.index += 1; break; }, else => { - result.id = Token.Id.Pipe; + result.id = .Pipe; break; }, }, - State.Equal => switch (c) { + .equal => switch (c) { '=' => { - result.id = Token.Id.EqualEqual; + result.id = .EqualEqual; self.index += 1; break; }, '>' => { - result.id = Token.Id.EqualAngleBracketRight; + result.id = .EqualAngleBracketRight; self.index += 1; break; }, else => { - result.id = Token.Id.Equal; + result.id = .Equal; break; }, }, - State.Minus => switch (c) { + .minus => switch (c) { '>' => { - result.id = Token.Id.Arrow; + result.id = .Arrow; self.index += 1; break; }, '=' => { - result.id = Token.Id.MinusEqual; + result.id = .MinusEqual; self.index += 1; break; }, '%' => { - state = State.MinusPercent; + state = .minus_percent; }, else => { - result.id = Token.Id.Minus; + result.id = .Minus; break; }, }, - State.MinusPercent => switch (c) { + .minus_percent => switch (c) { '=' => { - result.id = Token.Id.MinusPercentEqual; + result.id = .MinusPercentEqual; self.index += 1; break; }, else => { - result.id = Token.Id.MinusPercent; + result.id = .MinusPercent; break; }, }, - State.AngleBracketLeft => switch (c) { + .angle_bracket_left => switch (c) { '<' => { - state = State.AngleBracketAngleBracketLeft; + state = .angle_bracket_angle_bracket_left; }, '=' => { - result.id = Token.Id.AngleBracketLeftEqual; + result.id = .AngleBracketLeftEqual; self.index += 1; break; }, else => { - result.id = Token.Id.AngleBracketLeft; + result.id = .AngleBracketLeft; break; }, }, - State.AngleBracketAngleBracketLeft => switch (c) { + .angle_bracket_angle_bracket_left => switch (c) { '=' => { - result.id = Token.Id.AngleBracketAngleBracketLeftEqual; + result.id = .AngleBracketAngleBracketLeftEqual; self.index += 1; break; }, else => { - result.id = Token.Id.AngleBracketAngleBracketLeft; + result.id = .AngleBracketAngleBracketLeft; break; }, }, - State.AngleBracketRight => switch (c) { + .angle_bracket_right => switch (c) { '>' => { - state = State.AngleBracketAngleBracketRight; + state = .angle_bracket_angle_bracket_right; }, '=' => { - result.id = Token.Id.AngleBracketRightEqual; + result.id = .AngleBracketRightEqual; self.index += 1; break; }, else => { - result.id = Token.Id.AngleBracketRight; + result.id = .AngleBracketRight; break; }, }, - State.AngleBracketAngleBracketRight => switch (c) { + .angle_bracket_angle_bracket_right => switch (c) { '=' => { - result.id = Token.Id.AngleBracketAngleBracketRightEqual; + result.id = .AngleBracketAngleBracketRightEqual; self.index += 1; break; }, else => { - result.id = Token.Id.AngleBracketAngleBracketRight; + result.id = .AngleBracketAngleBracketRight; break; }, }, - State.Period => switch (c) { + .period => switch (c) { '.' => { - state = State.Period2; + state = .period_2; }, '*' => { - result.id = Token.Id.PeriodAsterisk; + result.id = .PeriodAsterisk; self.index += 1; break; }, else => { - result.id = Token.Id.Period; + result.id = .Period; break; }, }, - State.Period2 => switch (c) { + .period_2 => switch (c) { '.' => { - result.id = Token.Id.Ellipsis3; + result.id = .Ellipsis3; self.index += 1; break; }, else => { - result.id = Token.Id.Ellipsis2; + result.id = .Ellipsis2; break; }, }, - State.Slash => switch (c) { + .slash => switch (c) { '/' => { - state = State.LineCommentStart; - result.id = Token.Id.LineComment; + state = .line_comment_start; + result.id = .LineComment; }, '=' => { - result.id = Token.Id.SlashEqual; + result.id = .SlashEqual; self.index += 1; break; }, else => { - result.id = Token.Id.Slash; + result.id = .Slash; break; }, }, - State.LineCommentStart => switch (c) { + .line_comment_start => switch (c) { '/' => { - state = State.DocCommentStart; + state = .doc_comment_start; }, '!' => { - result.id = Token.Id.ContainerDocComment; - state = State.ContainerDocComment; + result.id = .ContainerDocComment; + state = .container_doc_comment; }, '\n' => break, else => { - state = State.LineComment; + state = .line_comment; self.checkLiteralCharacter(); }, }, - State.DocCommentStart => switch (c) { + .doc_comment_start => switch (c) { '/' => { - state = State.LineComment; + state = .line_comment; }, '\n' => { - result.id = Token.Id.DocComment; + result.id = .DocComment; break; }, else => { - state = State.DocComment; - result.id = Token.Id.DocComment; + state = .doc_comment; + result.id = .DocComment; self.checkLiteralCharacter(); }, }, - State.LineComment, State.DocComment, State.ContainerDocComment => switch (c) { + .line_comment, .doc_comment, .container_doc_comment => switch (c) { '\n' => break, else => self.checkLiteralCharacter(), }, - State.Zero => switch (c) { + .zero => switch (c) { 'b' => { - state = State.IntegerLiteralBinNoUnderscore; + state = .int_literal_bin_no_underscore; }, 'o' => { - state = State.IntegerLiteralOctNoUnderscore; + state = .int_literal_oct_no_underscore; }, 'x' => { - state = State.IntegerLiteralHexNoUnderscore; + state = .int_literal_hex_no_underscore; }, '0'...'9', '_', '.', 'e', 'E' => { // reinterpret as a decimal number self.index -= 1; - state = State.IntegerLiteralDec; + state = .int_literal_dec; }, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.IntegerLiteralBinNoUnderscore => switch (c) { + .int_literal_bin_no_underscore => switch (c) { '0'...'1' => { - state = State.IntegerLiteralBin; + state = .int_literal_bin; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.IntegerLiteralBin => switch (c) { + .int_literal_bin => switch (c) { '_' => { - state = State.IntegerLiteralBinNoUnderscore; + state = .int_literal_bin_no_underscore; }, '0'...'1' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.IntegerLiteralOctNoUnderscore => switch (c) { + .int_literal_oct_no_underscore => switch (c) { '0'...'7' => { - state = State.IntegerLiteralOct; + state = .int_literal_oct; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.IntegerLiteralOct => switch (c) { + .int_literal_oct => switch (c) { '_' => { - state = State.IntegerLiteralOctNoUnderscore; + state = .int_literal_oct_no_underscore; }, '0'...'7' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.IntegerLiteralDecNoUnderscore => switch (c) { + .int_literal_dec_no_underscore => switch (c) { '0'...'9' => { - state = State.IntegerLiteralDec; + state = .int_literal_dec; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.IntegerLiteralDec => switch (c) { + .int_literal_dec => switch (c) { '_' => { - state = State.IntegerLiteralDecNoUnderscore; + state = .int_literal_dec_no_underscore; }, '.' => { - state = State.NumberDotDec; - result.id = Token.Id.FloatLiteral; + state = .num_dot_dec; + result.id = .FloatLiteral; }, 'e', 'E' => { - state = State.FloatExponentUnsigned; - result.id = Token.Id.FloatLiteral; + state = .float_exponent_unsigned; + result.id = .FloatLiteral; }, '0'...'9' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.IntegerLiteralHexNoUnderscore => switch (c) { + .int_literal_hex_no_underscore => switch (c) { '0'...'9', 'a'...'f', 'A'...'F' => { - state = State.IntegerLiteralHex; + state = .int_literal_hex; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.IntegerLiteralHex => switch (c) { + .int_literal_hex => switch (c) { '_' => { - state = State.IntegerLiteralHexNoUnderscore; + state = .int_literal_hex_no_underscore; }, '.' => { - state = State.NumberDotHex; - result.id = Token.Id.FloatLiteral; + state = .num_dot_hex; + result.id = .FloatLiteral; }, 'p', 'P' => { - state = State.FloatExponentUnsigned; - result.id = Token.Id.FloatLiteral; + state = .float_exponent_unsigned; + result.id = .FloatLiteral; }, '0'...'9', 'a'...'f', 'A'...'F' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.NumberDotDec => switch (c) { + .num_dot_dec => switch (c) { '.' => { self.index -= 1; - state = State.Start; + state = .start; break; }, 'e', 'E' => { - state = State.FloatExponentUnsigned; + state = .float_exponent_unsigned; }, '0'...'9' => { - result.id = Token.Id.FloatLiteral; - state = State.FloatFractionDec; + result.id = .FloatLiteral; + state = .float_fraction_dec; }, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.NumberDotHex => switch (c) { + .num_dot_hex => switch (c) { '.' => { self.index -= 1; - state = State.Start; + state = .start; break; }, 'p', 'P' => { - state = State.FloatExponentUnsigned; + state = .float_exponent_unsigned; }, '0'...'9', 'a'...'f', 'A'...'F' => { - result.id = Token.Id.FloatLiteral; - state = State.FloatFractionHex; + result.id = .FloatLiteral; + state = .float_fraction_hex; }, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.FloatFractionDecNoUnderscore => switch (c) { + .float_fraction_dec_no_underscore => switch (c) { '0'...'9' => { - state = State.FloatFractionDec; + state = .float_fraction_dec; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.FloatFractionDec => switch (c) { + .float_fraction_dec => switch (c) { '_' => { - state = State.FloatFractionDecNoUnderscore; + state = .float_fraction_dec_no_underscore; }, 'e', 'E' => { - state = State.FloatExponentUnsigned; + state = .float_exponent_unsigned; }, '0'...'9' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.FloatFractionHexNoUnderscore => switch (c) { + .float_fraction_hex_no_underscore => switch (c) { '0'...'9', 'a'...'f', 'A'...'F' => { - state = State.FloatFractionHex; + state = .float_fraction_hex; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.FloatFractionHex => switch (c) { + .float_fraction_hex => switch (c) { '_' => { - state = State.FloatFractionHexNoUnderscore; + state = .float_fraction_hex_no_underscore; }, 'p', 'P' => { - state = State.FloatExponentUnsigned; + state = .float_exponent_unsigned; }, '0'...'9', 'a'...'f', 'A'...'F' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, }, - State.FloatExponentUnsigned => switch (c) { + .float_exponent_unsigned => switch (c) { '+', '-' => { - state = State.FloatExponentNumberNoUnderscore; + state = .float_exponent_num_no_underscore; }, else => { // reinterpret as a normal exponent number self.index -= 1; - state = State.FloatExponentNumberNoUnderscore; + state = .float_exponent_num_no_underscore; }, }, - State.FloatExponentNumberNoUnderscore => switch (c) { + .float_exponent_num_no_underscore => switch (c) { '0'...'9' => { - state = State.FloatExponentNumber; + state = .float_exponent_num; }, else => { - result.id = Token.Id.Invalid; + result.id = .Invalid; break; }, }, - State.FloatExponentNumber => switch (c) { + .float_exponent_num => switch (c) { '_' => { - state = State.FloatExponentNumberNoUnderscore; + state = .float_exponent_num_no_underscore; }, '0'...'9' => {}, else => { if (isIdentifierChar(c)) { - result.id = Token.Id.Invalid; + result.id = .Invalid; } break; }, @@ -1297,123 +1297,123 @@ pub const Tokenizer = struct { } } else if (self.index == self.buffer.len) { switch (state) { - State.Start, - State.IntegerLiteralDec, - State.IntegerLiteralBin, - State.IntegerLiteralOct, - State.IntegerLiteralHex, - State.NumberDotDec, - State.NumberDotHex, - State.FloatFractionDec, - State.FloatFractionHex, - State.FloatExponentNumber, - State.StringLiteral, // find this error later - State.MultilineStringLiteralLine, - State.Builtin, + .start, + .int_literal_dec, + .int_literal_bin, + .int_literal_oct, + .int_literal_hex, + .num_dot_dec, + .num_dot_hex, + .float_fraction_dec, + .float_fraction_hex, + .float_exponent_num, + .string_literal, // find this error later + .multiline_string_literal_line, + .builtin, => {}, - State.Identifier => { + .identifier => { if (Token.getKeyword(self.buffer[result.start..self.index])) |id| { result.id = id; } }, - State.LineCommentStart, State.LineComment => { - result.id = Token.Id.LineComment; + .line_comment, .line_comment_start => { + result.id = .LineComment; }, - State.DocComment, State.DocCommentStart => { - result.id = Token.Id.DocComment; + .doc_comment, .doc_comment_start => { + result.id = .DocComment; }, - State.ContainerDocComment => { - result.id = Token.Id.ContainerDocComment; + .container_doc_comment => { + result.id = .ContainerDocComment; }, - State.IntegerLiteralDecNoUnderscore, - State.IntegerLiteralBinNoUnderscore, - State.IntegerLiteralOctNoUnderscore, - State.IntegerLiteralHexNoUnderscore, - State.FloatFractionDecNoUnderscore, - State.FloatFractionHexNoUnderscore, - State.FloatExponentNumberNoUnderscore, - State.FloatExponentUnsigned, - State.SawAtSign, - State.Backslash, - State.CharLiteral, - State.CharLiteralBackslash, - State.CharLiteralHexEscape, - State.CharLiteralUnicodeEscapeSawU, - State.CharLiteralUnicodeEscape, - State.CharLiteralUnicodeInvalid, - State.CharLiteralEnd, - State.CharLiteralUnicode, - State.StringLiteralBackslash, + .int_literal_dec_no_underscore, + .int_literal_bin_no_underscore, + .int_literal_oct_no_underscore, + .int_literal_hex_no_underscore, + .float_fraction_dec_no_underscore, + .float_fraction_hex_no_underscore, + .float_exponent_num_no_underscore, + .float_exponent_unsigned, + .saw_at_sign, + .backslash, + .char_literal, + .char_literal_backslash, + .char_literal_hex_escape, + .char_literal_unicode_escape_saw_u, + .char_literal_unicode_escape, + .char_literal_unicode_invalid, + .char_literal_end, + .char_literal_unicode, + .string_literal_backslash, => { - result.id = Token.Id.Invalid; + result.id = .Invalid; }, - State.Equal => { - result.id = Token.Id.Equal; + .equal => { + result.id = .Equal; }, - State.Bang => { - result.id = Token.Id.Bang; + .bang => { + result.id = .Bang; }, - State.Minus => { - result.id = Token.Id.Minus; + .minus => { + result.id = .Minus; }, - State.Slash => { - result.id = Token.Id.Slash; + .slash => { + result.id = .Slash; }, - State.Zero => { - result.id = Token.Id.IntegerLiteral; + .zero => { + result.id = .IntegerLiteral; }, - State.Ampersand => { - result.id = Token.Id.Ampersand; + .ampersand => { + result.id = .Ampersand; }, - State.Period => { - result.id = Token.Id.Period; + .period => { + result.id = .Period; }, - State.Period2 => { - result.id = Token.Id.Ellipsis2; + .period_2 => { + result.id = .Ellipsis2; }, - State.Pipe => { - result.id = Token.Id.Pipe; + .pipe => { + result.id = .Pipe; }, - State.AngleBracketAngleBracketRight => { - result.id = Token.Id.AngleBracketAngleBracketRight; + .angle_bracket_angle_bracket_right => { + result.id = .AngleBracketAngleBracketRight; }, - State.AngleBracketRight => { - result.id = Token.Id.AngleBracketRight; + .angle_bracket_right => { + result.id = .AngleBracketRight; }, - State.AngleBracketAngleBracketLeft => { - result.id = Token.Id.AngleBracketAngleBracketLeft; + .angle_bracket_angle_bracket_left => { + result.id = .AngleBracketAngleBracketLeft; }, - State.AngleBracketLeft => { - result.id = Token.Id.AngleBracketLeft; + .angle_bracket_left => { + result.id = .AngleBracketLeft; }, - State.PlusPercent => { - result.id = Token.Id.PlusPercent; + .plus_percent => { + result.id = .PlusPercent; }, - State.Plus => { - result.id = Token.Id.Plus; + .plus => { + result.id = .Plus; }, - State.Percent => { - result.id = Token.Id.Percent; + .percent => { + result.id = .Percent; }, - State.Caret => { - result.id = Token.Id.Caret; + .caret => { + result.id = .Caret; }, - State.AsteriskPercent => { - result.id = Token.Id.AsteriskPercent; + .asterisk_percent => { + result.id = .AsteriskPercent; }, - State.Asterisk => { - result.id = Token.Id.Asterisk; + .asterisk => { + result.id = .Asterisk; }, - State.MinusPercent => { - result.id = Token.Id.MinusPercent; + .minus_percent => { + result.id = .MinusPercent; }, } } - if (result.id == Token.Id.Eof) { + if (result.id == .Eof) { if (self.pending_invalid_token) |token| { self.pending_invalid_token = null; return token; @@ -1428,8 +1428,8 @@ pub const Tokenizer = struct { if (self.pending_invalid_token != null) return; const invalid_length = self.getInvalidCharacterLength(); if (invalid_length == 0) return; - self.pending_invalid_token = Token{ - .id = Token.Id.Invalid, + self.pending_invalid_token = .{ + .id = .Invalid, .start = self.index, .end = self.index + invalid_length, }; @@ -1474,7 +1474,7 @@ pub const Tokenizer = struct { }; test "tokenizer" { - testTokenize("test", &[_]Token.Id{Token.Id.Keyword_test}); + testTokenize("test", &[_]Token.Id{.Keyword_test}); } test "tokenizer - unknown length pointer and then c pointer" { @@ -1482,15 +1482,15 @@ test "tokenizer - unknown length pointer and then c pointer" { \\[*]u8 \\[*c]u8 , &[_]Token.Id{ - Token.Id.LBracket, - Token.Id.Asterisk, - Token.Id.RBracket, - Token.Id.Identifier, - Token.Id.LBracket, - Token.Id.Asterisk, - Token.Id.Identifier, - Token.Id.RBracket, - Token.Id.Identifier, + .LBracket, + .Asterisk, + .RBracket, + .Identifier, + .LBracket, + .Asterisk, + .Identifier, + .RBracket, + .Identifier, }); } @@ -1561,125 +1561,125 @@ test "tokenizer - char literal with unicode code point" { test "tokenizer - float literal e exponent" { testTokenize("a = 4.94065645841246544177e-324;\n", &[_]Token.Id{ - Token.Id.Identifier, - Token.Id.Equal, - Token.Id.FloatLiteral, - Token.Id.Semicolon, + .Identifier, + .Equal, + .FloatLiteral, + .Semicolon, }); } test "tokenizer - float literal p exponent" { testTokenize("a = 0x1.a827999fcef32p+1022;\n", &[_]Token.Id{ - Token.Id.Identifier, - Token.Id.Equal, - Token.Id.FloatLiteral, - Token.Id.Semicolon, + .Identifier, + .Equal, + .FloatLiteral, + .Semicolon, }); } test "tokenizer - chars" { - testTokenize("'c'", &[_]Token.Id{Token.Id.CharLiteral}); + testTokenize("'c'", &[_]Token.Id{.CharLiteral}); } test "tokenizer - invalid token characters" { - testTokenize("#", &[_]Token.Id{Token.Id.Invalid}); - testTokenize("`", &[_]Token.Id{Token.Id.Invalid}); - testTokenize("'c", &[_]Token.Id{Token.Id.Invalid}); - testTokenize("'", &[_]Token.Id{Token.Id.Invalid}); - testTokenize("''", &[_]Token.Id{ Token.Id.Invalid, Token.Id.Invalid }); + testTokenize("#", &[_]Token.Id{.Invalid}); + testTokenize("`", &[_]Token.Id{.Invalid}); + testTokenize("'c", &[_]Token.Id{.Invalid}); + testTokenize("'", &[_]Token.Id{.Invalid}); + testTokenize("''", &[_]Token.Id{ .Invalid, .Invalid }); } test "tokenizer - invalid literal/comment characters" { testTokenize("\"\x00\"", &[_]Token.Id{ - Token.Id.StringLiteral, - Token.Id.Invalid, + .StringLiteral, + .Invalid, }); testTokenize("//\x00", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\x1f", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\x7f", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); } test "tokenizer - utf8" { - testTokenize("//\xc2\x80", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("//\xf4\x8f\xbf\xbf", &[_]Token.Id{Token.Id.LineComment}); + testTokenize("//\xc2\x80", &[_]Token.Id{.LineComment}); + testTokenize("//\xf4\x8f\xbf\xbf", &[_]Token.Id{.LineComment}); } test "tokenizer - invalid utf8" { testTokenize("//\x80", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xbf", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xf8", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xff", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xc2\xc0", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xe0", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xf0", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xf0\x90\x80\xc0", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); } test "tokenizer - illegal unicode codepoints" { // unicode newline characters.U+0085, U+2028, U+2029 - testTokenize("//\xc2\x84", &[_]Token.Id{Token.Id.LineComment}); + testTokenize("//\xc2\x84", &[_]Token.Id{.LineComment}); testTokenize("//\xc2\x85", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); - testTokenize("//\xc2\x86", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("//\xe2\x80\xa7", &[_]Token.Id{Token.Id.LineComment}); + testTokenize("//\xc2\x86", &[_]Token.Id{.LineComment}); + testTokenize("//\xe2\x80\xa7", &[_]Token.Id{.LineComment}); testTokenize("//\xe2\x80\xa8", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); testTokenize("//\xe2\x80\xa9", &[_]Token.Id{ - Token.Id.LineComment, - Token.Id.Invalid, + .LineComment, + .Invalid, }); - testTokenize("//\xe2\x80\xaa", &[_]Token.Id{Token.Id.LineComment}); + testTokenize("//\xe2\x80\xaa", &[_]Token.Id{.LineComment}); } test "tokenizer - string identifier and builtin fns" { testTokenize( \\const @"if" = @import("std"); , &[_]Token.Id{ - Token.Id.Keyword_const, - Token.Id.Identifier, - Token.Id.Equal, - Token.Id.Builtin, - Token.Id.LParen, - Token.Id.StringLiteral, - Token.Id.RParen, - Token.Id.Semicolon, + .Keyword_const, + .Identifier, + .Equal, + .Builtin, + .LParen, + .StringLiteral, + .RParen, + .Semicolon, }); } @@ -1687,26 +1687,26 @@ test "tokenizer - multiline string literal with literal tab" { testTokenize( \\\\foo bar , &[_]Token.Id{ - Token.Id.MultilineStringLiteralLine, + .MultilineStringLiteralLine, }); } test "tokenizer - pipe and then invalid" { testTokenize("||=", &[_]Token.Id{ - Token.Id.PipePipe, - Token.Id.Equal, + .PipePipe, + .Equal, }); } test "tokenizer - line comment and doc comment" { - testTokenize("//", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("// a / b", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("// /", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("/// a", &[_]Token.Id{Token.Id.DocComment}); - testTokenize("///", &[_]Token.Id{Token.Id.DocComment}); - testTokenize("////", &[_]Token.Id{Token.Id.LineComment}); - testTokenize("//!", &[_]Token.Id{Token.Id.ContainerDocComment}); - testTokenize("//!!", &[_]Token.Id{Token.Id.ContainerDocComment}); + testTokenize("//", &[_]Token.Id{.LineComment}); + testTokenize("// a / b", &[_]Token.Id{.LineComment}); + testTokenize("// /", &[_]Token.Id{.LineComment}); + testTokenize("/// a", &[_]Token.Id{.DocComment}); + testTokenize("///", &[_]Token.Id{.DocComment}); + testTokenize("////", &[_]Token.Id{.LineComment}); + testTokenize("//!", &[_]Token.Id{.ContainerDocComment}); + testTokenize("//!!", &[_]Token.Id{.ContainerDocComment}); } test "tokenizer - line comment followed by identifier" { @@ -1715,28 +1715,28 @@ test "tokenizer - line comment followed by identifier" { \\ // another \\ Another, , &[_]Token.Id{ - Token.Id.Identifier, - Token.Id.Comma, - Token.Id.LineComment, - Token.Id.Identifier, - Token.Id.Comma, + .Identifier, + .Comma, + .LineComment, + .Identifier, + .Comma, }); } test "tokenizer - UTF-8 BOM is recognized and skipped" { testTokenize("\xEF\xBB\xBFa;\n", &[_]Token.Id{ - Token.Id.Identifier, - Token.Id.Semicolon, + .Identifier, + .Semicolon, }); } test "correctly parse pointer assignment" { testTokenize("b.*=3;\n", &[_]Token.Id{ - Token.Id.Identifier, - Token.Id.PeriodAsterisk, - Token.Id.Equal, - Token.Id.IntegerLiteral, - Token.Id.Semicolon, + .Identifier, + .PeriodAsterisk, + .Equal, + .IntegerLiteral, + .Semicolon, }); } @@ -1979,5 +1979,5 @@ fn testTokenize(source: []const u8, expected_tokens: []const Token.Id) void { } } const last_token = tokenizer.next(); - std.testing.expect(last_token.id == Token.Id.Eof); + std.testing.expect(last_token.id == .Eof); } From ad71d959d7d1b5f3a771dc2c1eaf37dbd7cd0852 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 23:28:04 +0300 Subject: [PATCH 66/74] correctly recover from invalid top level declarations --- lib/std/zig/parse.zig | 20 +++++++++++++------- lib/std/zig/parser_test.zig | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 6052d92d6a..d8d1d4b427 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -130,7 +130,13 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All const visib_token = eatToken(it, .Keyword_pub); - if (try parseTopLevelDecl(arena, it, tree)) |node| { + if (parseTopLevelDecl(arena, it, tree) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, + error.ParseError => { + // try again + continue; + }, + }) |node| { if (field_state == .seen) { field_state = .{ .end = visib_token orelse node.firstToken() }; } @@ -315,7 +321,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl /// / KEYWORD_usingnamespace Expr SEMICOLON -fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!?*Node { +fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { var lib_name: ?*Node = null; const extern_export_inline_token = blk: { if (eatToken(it, .Keyword_export)) |token| break :blk token; @@ -334,7 +340,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocat // this fn will likely have a body so we // use findEndOfBlock instead of findToken. findEndOfBlock(it); - return null; + return error.ParseError; }, }) |node| { const fn_node = node.cast(Node.FnProto).?; @@ -373,7 +379,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocat error.ParseError => { // try to skip to next decl findToken(it, .Semicolon); - return null; + return error.ParseError; }, }) |node| { var var_decl = node.cast(Node.VarDecl).?; @@ -388,8 +394,8 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocat try tree.errors.push(.{ .ExpectedVarDecl = .{ .token = it.index }, }); - // ignore this, try to find next decl by skipping the next block - findEndOfBlock(it); + // ignore this and try again; + return error.ParseError; } if (extern_export_inline_token) |token| { @@ -404,7 +410,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocat error.ParseError => { // try to skip to next decl findToken(it, .Semicolon); - return null; + return error.ParseError; }, }; } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index e3bc20bd10..7ddf9cc9c8 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -62,6 +62,28 @@ test "recovery: missing return type" { }); } +test "recovery: continue after invalid decl" { + try testError( + \\fn foo { + \\ inline; + \\} + \\test "" { + \\ a && b; + \\} + , &[_]Error{ + .ExpectedToken, + .InvalidAnd, + }); + try testError( + \\threadlocal test "" { + \\ a && b; + \\} + , &[_]Error{ + .ExpectedVarDecl, + .InvalidAnd, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, From 1f81887a7863545d8b89bff6cc7d31941da0abf0 Mon Sep 17 00:00:00 2001 From: Vexu Date: Wed, 13 May 2020 23:35:58 +0300 Subject: [PATCH 67/74] recover after invalid inline/extern --- lib/std/zig/ast.zig | 4 ++++ lib/std/zig/parse.zig | 17 ++++++++++------- lib/std/zig/parser_test.zig | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index afb7fce23e..26bff31bbd 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -129,6 +129,7 @@ pub const Error = union(enum) { ExpectedStatement: ExpectedStatement, ExpectedVarDeclOrFn: ExpectedVarDeclOrFn, ExpectedVarDecl: ExpectedVarDecl, + ExpectedFn: ExpectedFn, ExpectedReturnType: ExpectedReturnType, ExpectedAggregateKw: ExpectedAggregateKw, UnattachedDocComment: UnattachedDocComment, @@ -179,6 +180,7 @@ pub const Error = union(enum) { .ExpectedStatement => |*x| return x.render(tokens, stream), .ExpectedVarDeclOrFn => |*x| return x.render(tokens, stream), .ExpectedVarDecl => |*x| return x.render(tokens, stream), + .ExpectedFn => |*x| return x.render(tokens, stream), .ExpectedReturnType => |*x| return x.render(tokens, stream), .ExpectedAggregateKw => |*x| return x.render(tokens, stream), .UnattachedDocComment => |*x| return x.render(tokens, stream), @@ -231,6 +233,7 @@ pub const Error = union(enum) { .ExpectedStatement => |x| return x.token, .ExpectedVarDeclOrFn => |x| return x.token, .ExpectedVarDecl => |x| return x.token, + .ExpectedFn => |x| return x.token, .ExpectedReturnType => |x| return x.token, .ExpectedAggregateKw => |x| return x.token, .UnattachedDocComment => |x| return x.token, @@ -280,6 +283,7 @@ pub const Error = union(enum) { pub const ExpectedStatement = SingleTokenError("Expected statement, found '{}'"); pub const ExpectedVarDeclOrFn = SingleTokenError("Expected variable declaration or function, found '{}'"); pub const ExpectedVarDecl = SingleTokenError("Expected variable declaration, found '{}'"); + pub const ExpectedFn = SingleTokenError("Expected function, found '{}'"); pub const ExpectedReturnType = SingleTokenError("Expected 'var' or return type expression, found '{}'"); pub const ExpectedAggregateKw = SingleTokenError("Expected '" ++ Token.Id.Keyword_struct.symbol() ++ "', '" ++ Token.Id.Keyword_union.symbol() ++ "', or '" ++ Token.Id.Keyword_enum.symbol() ++ "', found '{}'"); pub const ExpectedEqOrSemi = SingleTokenError("Expected '=' or ';', found '{}'"); diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index d8d1d4b427..cbd5336ca2 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -360,15 +360,17 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? try tree.errors.push(.{ .ExpectedSemiOrLBrace = .{ .token = it.index }, }); - return null; + return error.ParseError; } if (extern_export_inline_token) |token| { if (tree.tokens.at(token).id == .Keyword_inline or tree.tokens.at(token).id == .Keyword_noinline) { - putBackToken(it, token); - return null; + try tree.errors.push(.{ + .ExpectedFn = .{ .token = it.index }, + }); + return error.ParseError; } } @@ -399,10 +401,11 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? } if (extern_export_inline_token) |token| { - if (lib_name) |string_literal_node| - putBackToken(it, string_literal_node.cast(Node.StringLiteral).?.token); - putBackToken(it, token); - return null; + try tree.errors.push(.{ + .ExpectedVarDeclOrFn = .{ .token = it.index }, + }); + // ignore this and try again; + return error.ParseError; } return parseUse(arena, it, tree) catch |err| switch (err) { diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 7ddf9cc9c8..d837769802 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -84,6 +84,21 @@ test "recovery: continue after invalid decl" { }); } +test "recovery: invalid extern/inline" { + try testError( + \\inline test "" { a && b; } + , &[_]Error{ + .ExpectedFn, + .InvalidAnd, + }); + try testError( + \\extern "" test "" { a && b; } + , &[_]Error{ + .ExpectedVarDeclOrFn, + .InvalidAnd, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, From c3b76d091337ba60d2ccb3632b525e5a42d1f2c5 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 00:16:56 +0300 Subject: [PATCH 68/74] recover from invalid builtin/async call --- lib/std/zig/ast.zig | 1 + lib/std/zig/parse.zig | 18 +++++++++++++----- lib/std/zig/parser_test.zig | 9 ++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 26bff31bbd..6fb1ce012b 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -926,6 +926,7 @@ pub const Node = struct { if (i < 1) return node; i -= 1; }, + .Invalid => unreachable, } if (self.body_node) |body_node| { diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index cbd5336ca2..6c664bbda2 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -172,6 +172,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All .ExpectedPubItem = .{ .token = it.index }, }); // ignore this pub + continue; } if (parseContainerField(arena, it, tree) catch |err| switch (err) { @@ -1017,7 +1018,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node const node = try arena.create(Node.ControlFlowExpression); node.* = .{ .ltoken = token, - .kind = Node.ControlFlowExpression.Kind{ .Break = label }, + .kind = .{ .Break = label }, .rhs = expr_node, }; return &node.base; @@ -1053,7 +1054,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node const node = try arena.create(Node.ControlFlowExpression); node.* = .{ .ltoken = token, - .kind = Node.ControlFlowExpression.Kind{ .Continue = label }, + .kind = .{ .Continue = label }, .rhs = null, }; return &node.base; @@ -1077,7 +1078,7 @@ fn parsePrimaryExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node const node = try arena.create(Node.ControlFlowExpression); node.* = .{ .ltoken = token, - .kind = Node.ControlFlowExpression.Kind.Return, + .kind = .Return, .rhs = expr_node, }; return &node.base; @@ -1322,7 +1323,8 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { try tree.errors.push(.{ .ExpectedParamList = .{ .token = it.index }, }); - return null; + // ignore this, continue parsing + return res; }; const node = try arena.create(Node.SuffixOp); node.* = .{ @@ -2908,7 +2910,13 @@ fn parseBuiltinCall(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node try tree.errors.push(.{ .ExpectedParamList = .{ .token = it.index }, }); - return error.ParseError; + + // lets pretend this was an identifier so we can continue parsing + const node = try arena.create(Node.Identifier); + node.* = .{ + .token = token, + }; + return &node.base; }; const node = try arena.create(Node.BuiltinCall); node.* = .{ diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index d837769802..34c61b6bb4 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -67,19 +67,22 @@ test "recovery: continue after invalid decl" { \\fn foo { \\ inline; \\} - \\test "" { - \\ a && b; + \\pub test "" { + \\ async a && b; \\} , &[_]Error{ .ExpectedToken, + .ExpectedPubItem, + .ExpectedParamList, .InvalidAnd, }); try testError( \\threadlocal test "" { - \\ a && b; + \\ @a && b; \\} , &[_]Error{ .ExpectedVarDecl, + .ExpectedParamList, .InvalidAnd, }); } From ac319b27348f60e37f3f1b478fee00202280715f Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 11:19:14 +0300 Subject: [PATCH 69/74] remove useless nosuspend parsing nosuspend cannot be used in a type expression and all other use casesare covered by PrimaryExpr --- doc/langref.html.in | 3 +++ lib/std/zig/parse.zig | 10 ---------- src/parser.cpp | 9 --------- 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index 5bf91ca70f..0733540478 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -10096,6 +10096,7 @@ ContainerField <- IDENTIFIER (COLON TypeExpr)? (EQUAL Expr)? Statement <- KEYWORD_comptime? VarDecl / KEYWORD_comptime BlockExprStatement + / KEYWORD_nosuspend BlockExprStatement / KEYWORD_suspend (SEMICOLON / BlockExprStatement) / KEYWORD_defer BlockExprStatement / KEYWORD_errdefer BlockExprStatement @@ -10152,6 +10153,7 @@ PrimaryExpr / IfExpr / KEYWORD_break BreakLabel? Expr? / KEYWORD_comptime Expr + / KEYWORD_nosuspend Expr / KEYWORD_continue BreakLabel? / KEYWORD_resume Expr / KEYWORD_return Expr? @@ -10514,6 +10516,7 @@ KEYWORD_for <- 'for' end_of_word KEYWORD_if <- 'if' end_of_word KEYWORD_inline <- 'inline' end_of_word KEYWORD_noalias <- 'noalias' end_of_word +KEYWORD_nosuspend <- 'nosuspend' end_of_word KEYWORD_null <- 'null' end_of_word KEYWORD_or <- 'or' end_of_word KEYWORD_orelse <- 'orelse' end_of_word diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 6c664bbda2..c16dba4a11 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -1389,7 +1389,6 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { /// / IfTypeExpr /// / INTEGER /// / KEYWORD_comptime TypeExpr -/// / KEYWORD_nosuspend TypeExpr /// / KEYWORD_error DOT IDENTIFIER /// / KEYWORD_false /// / KEYWORD_null @@ -1428,15 +1427,6 @@ fn parsePrimaryTypeExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*N }; return &node.base; } - if (eatToken(it, .Keyword_nosuspend)) |token| { - const expr = (try parseTypeExpr(arena, it, tree)) orelse return null; - const node = try arena.create(Node.Nosuspend); - node.* = .{ - .nosuspend_token = token, - .expr = expr, - }; - return &node.base; - } if (eatToken(it, .Keyword_error)) |token| { const period = try expectToken(it, tree, .Period); const identifier = try expectNode(arena, it, tree, parseIdentifier, .{ diff --git a/src/parser.cpp b/src/parser.cpp index 1a929cd1b1..fc9814f393 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1609,7 +1609,6 @@ static AstNode *ast_parse_suffix_expr(ParseContext *pc) { // / IfTypeExpr // / INTEGER // / KEYWORD_comptime TypeExpr -// / KEYWORD_nosuspend TypeExpr // / KEYWORD_error DOT IDENTIFIER // / KEYWORD_false // / KEYWORD_null @@ -1711,14 +1710,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) { return res; } - Token *nosuspend = eat_token_if(pc, TokenIdKeywordNoSuspend); - if (nosuspend != nullptr) { - AstNode *expr = ast_expect(pc, ast_parse_type_expr); - AstNode *res = ast_create_node(pc, NodeTypeNoSuspend, nosuspend); - res->data.nosuspend_expr.expr = expr; - return res; - } - Token *error = eat_token_if(pc, TokenIdKeywordError); if (error != nullptr) { Token *dot = expect_token(pc, TokenIdDot); From 89f2923a8aad5119b1506c3b8e08464e132c228e Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 11:19:50 +0300 Subject: [PATCH 70/74] recover from missing semicolon --- lib/std/zig/parse.zig | 16 +++++++++++++--- lib/std/zig/parser_test.zig | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index c16dba4a11..24bb164685 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -667,7 +667,12 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No if (try parseLabeledStatement(arena, it, tree)) |node| return node; if (try parseSwitchExpr(arena, it, tree)) |node| return node; if (try parseAssignExpr(arena, it, tree)) |node| { - _ = try expectToken(it, tree, .Semicolon); + _ = eatToken(it, .Semicolon) orelse { + try tree.errors.push(.{ + .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, + }); + // pretend we saw a semicolon and continue parsing + }; return node; } @@ -911,7 +916,12 @@ fn parseWhileStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No fn parseBlockExprStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { if (try parseBlockExpr(arena, it, tree)) |node| return node; if (try parseAssignExpr(arena, it, tree)) |node| { - _ = try expectToken(it, tree, .Semicolon); + _ = eatToken(it, .Semicolon) orelse { + try tree.errors.push(.{ + .ExpectedToken = .{ .token = it.index, .expected_id = .Semicolon }, + }); + // pretend we saw a semicolon and continue parsing + }; return node; } return null; @@ -3072,7 +3082,7 @@ fn parseDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.D } /// Eat a single-line doc comment on the same line as another node -fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) Allocator.Error!?*Node.DocComment { +fn parseAppendedDocComment(arena: *Allocator, it: *TokenIterator, tree: *Tree, after_token: TokenIndex) !?*Node.DocComment { const comment_token = eatToken(it, .DocComment) orelse return null; if (tree.tokensOnSameLine(after_token, comment_token)) { const node = try arena.create(Node.DocComment); diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 34c61b6bb4..a367c2ff0b 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -102,6 +102,23 @@ test "recovery: invalid extern/inline" { }); } +test "recovery: missing semicolon" { + try testError( + \\test "" { + \\ comptime a && b + \\ c && d + \\ @foo + \\} + , &[_]Error{ + .InvalidAnd, + .ExpectedToken, + .InvalidAnd, + .ExpectedToken, + .ExpectedParamList, + .ExpectedToken, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, From a32e240540895af536fdeb98db448ee745def59a Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 12:09:40 +0300 Subject: [PATCH 71/74] improve recovery from invalid container members Instead of trying to find the end of the block or the next comma/semicolon we no try to find the next token that can start a container member. --- lib/std/zig/parse.zig | 98 +++++++++++++++++++++++++++++-------- lib/std/zig/parser_test.zig | 21 ++++++++ 2 files changed, 99 insertions(+), 20 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 24bb164685..b4b80669a1 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -59,10 +59,13 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error node.* = .{ .decls = try parseContainerMembers(arena, it, tree), .eof_token = eatToken(it, .Eof) orelse blk: { + // parseContainerMembers will try to skip as much + // invalid tokens as it can so this can only be a '}' + const tok = eatToken(it, .RBrace).?; try tree.errors.push(.{ - .ExpectedContainerMembers = .{ .token = it.index }, + .ExpectedContainerMembers = .{ .token = tok }, }); - break :blk undefined; + break :blk tok; }, }; return node; @@ -101,7 +104,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All if (parseTestDecl(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - findEndOfBlock(it); + findNextContainerMember(it); continue; }, }) |node| { @@ -116,7 +119,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All if (parseTopLevelComptime(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - findEndOfBlock(it); + findNextContainerMember(it); continue; }, }) |node| { @@ -178,8 +181,8 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All if (parseContainerField(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - // attempt to recover by finding a comma - findToken(it, .Comma); + // attempt to recover + findNextContainerMember(it); continue; }, }) |node| { @@ -198,7 +201,21 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All const field = node.cast(Node.ContainerField).?; field.doc_comments = doc_comments; try list.push(node); - const comma = eatToken(it, .Comma) orelse break; + const comma = eatToken(it, .Comma) orelse { + // try to continue parsing + const index = it.index; + findNextContainerMember(it); + switch (it.peek().?.id) { + .Eof, .RBrace => break, + else => { + // add error and continue + try tree.errors.push(.{ + .ExpectedToken = .{ .token = index, .expected_id = .Comma }, + }); + continue; + } + } + }; if (try parseAppendedDocComment(arena, it, tree, comma)) |appended_comment| field.doc_comments = appended_comment; continue; @@ -210,22 +227,63 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All .UnattachedDocComment = .{ .token = doc_comments.?.firstToken() }, }); } - break; + + switch (it.peek().?.id) { + .Eof, .RBrace => break, + else => { + // this was likely not supposed to end yet, + // try to find the next declaration + const index = it.index; + findNextContainerMember(it); + try tree.errors.push(.{ + .ExpectedContainerMembers = .{ .token = index }, + }); + }, + } } return list; } -/// Attempts to find a closing brace. -fn findEndOfBlock(it: *TokenIterator) void { - var count: u32 = 0; +fn findNextContainerMember(it: *TokenIterator) void { + var level: u32 = 0; while (true) { const tok = nextToken(it); switch (tok.ptr.id) { - .LBrace => count += 1, - .RBrace => { - if (count <= 1) return; - count -= 1; + // any of these can start a new top level declaration + .Keyword_test, + .Keyword_comptime, + .Keyword_pub, + .Keyword_export, + .Keyword_extern, + .Keyword_inline, + .Keyword_noinline, + .Keyword_usingnamespace, + .Keyword_threadlocal, + .Keyword_const, + .Keyword_var, + .Keyword_fn, + .Identifier, + => { + if (level == 0) { + putBackToken(it, tok.index); + return; + } + }, + .Comma, .Semicolon => { + // this decl was likely meant to end here + if (level == 0) { + return; + } + }, + .LParen, .LBracket, .LBrace => level += 1, + .RParen, .RBracket, .RBrace => { + if (level == 0) { + // end of container, exit + putBackToken(it, tok.index); + return; + } + level -= 1; }, .Eof => { putBackToken(it, tok.index); @@ -338,9 +396,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? if (parseFnProto(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - // this fn will likely have a body so we - // use findEndOfBlock instead of findToken. - findEndOfBlock(it); + findNextContainerMember(it); return error.ParseError; }, }) |node| { @@ -381,7 +437,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? error.OutOfMemory => return error.OutOfMemory, error.ParseError => { // try to skip to next decl - findToken(it, .Semicolon); + findNextContainerMember(it); return error.ParseError; }, }) |node| { @@ -413,7 +469,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? error.OutOfMemory => return error.OutOfMemory, error.ParseError => { // try to skip to next decl - findToken(it, .Semicolon); + findNextContainerMember(it); return error.ParseError; }, }; @@ -3215,6 +3271,8 @@ fn expectToken(it: *TokenIterator, tree: *Tree, id: Token.Id) Error!TokenIndex { try tree.errors.push(.{ .ExpectedToken = .{ .token = token.index, .expected_id = id }, }); + // go back so that we can recover properly + putBackToken(it, token.index); return error.ParseError; } return token.index; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index a367c2ff0b..8cbf2d4610 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -119,6 +119,25 @@ test "recovery: missing semicolon" { }); } +test "recovery: invalid container members" { + try testError( + \\usingnamespace; + \\foo+ + \\bar@, + \\while (a == 2) { test "" {}} + \\test "" { + \\ a && b + \\} + , &[_]Error{ + .ExpectedExpr, + .ExpectedToken, + .ExpectedToken, + .ExpectedContainerMembers, + .InvalidAnd, + .ExpectedToken, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, @@ -2953,6 +2972,8 @@ test "zig fmt: extern without container keyword returns error" { \\ , &[_]Error{ .ExpectedExpr, + .ExpectedVarDeclOrFn, + .ExpectedContainerMembers, }); } From c4552ee8edec961defb161e1b828a818f8d407bb Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 17:18:14 +0300 Subject: [PATCH 72/74] store rparen in ReturnType.Invalid This is useful for getting a partial function signature --- lib/std/zig/ast.zig | 2 +- lib/std/zig/parse.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 6fb1ce012b..351162bec0 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -897,7 +897,7 @@ pub const Node = struct { pub const ReturnType = union(enum) { Explicit: *Node, InferErrorSet: *Node, - Invalid, + Invalid: TokenIndex, }; pub fn iterate(self: *FnProto, index: usize) ?*Node { diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index b4b80669a1..98b1e9d329 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -518,7 +518,7 @@ fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { // TODO https://github.com/ziglang/zig/issues/3750 const R = Node.FnProto.ReturnType; const return_type = if (return_type_expr == null) - R{ .Invalid = {} } + R{ .Invalid = rparen } else if (exclamation_token != null) R{ .InferErrorSet = return_type_expr.? } else From c77fee03448817366a2cda98915bc31ba8f2b451 Mon Sep 17 00:00:00 2001 From: Vexu Date: Thu, 14 May 2020 19:56:55 +0300 Subject: [PATCH 73/74] fix infinite loop findToken wasn't as generic as I thought it was --- lib/std/zig/parse.zig | 28 ++++++++++++++++------------ lib/std/zig/parser_test.zig | 10 ++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 98b1e9d329..74945b1b33 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -213,7 +213,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All .ExpectedToken = .{ .token = index, .expected_id = .Comma }, }); continue; - } + }, } }; if (try parseAppendedDocComment(arena, it, tree, comma)) |appended_comment| @@ -245,6 +245,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All return list; } +/// Attempts to find next container member by searching for certain tokens fn findNextContainerMember(it: *TokenIterator) void { var level: u32 = 0; while (true) { @@ -294,27 +295,30 @@ fn findNextContainerMember(it: *TokenIterator) void { } } -/// Attempts to find `wanted` token, keeps track of parentheses. -fn findToken(it: *TokenIterator, wanted: Token.Id) void { - var count: u32 = 0; +/// Attempts to find the next statement by searching for a semicolon +fn findNextStmt(it: *TokenIterator) void { + var level: u32 = 0; while (true) { const tok = nextToken(it); switch (tok.ptr.id) { - .LParen, .LBracket, .LBrace => count += 1, - .RParen, .RBracket, .RBrace => { - if (count == 0) { + .LBrace => level += 1, + .RBrace => { + if (level == 0) { putBackToken(it, tok.index); return; } - count -= 1; + level -= 1; + }, + .Semicolon => { + if (level == 0) { + return; + } }, .Eof => { putBackToken(it, tok.index); return; }, - else => { - if (tok.ptr.id == wanted and count == 0) return; - }, + else => {}, } } } @@ -1186,7 +1190,7 @@ fn parseBlock(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { // try to skip to the next statement - findToken(it, .Semicolon); + findNextStmt(it); continue; }, }) orelse break; diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 8cbf2d4610..f92cc5a222 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -138,6 +138,16 @@ test "recovery: invalid container members" { }); } +test "recovery: invalid parameter" { + try testError( + \\fn main() void { + \\ a(comptime T: type) + \\} + , &[_]Error{ + .ExpectedToken, + }); +} + test "zig fmt: top-level fields" { try testCanonical( \\a: did_you_know, From 440189a04ae4baa4a20114fe1d30f0eb585bacc4 Mon Sep 17 00:00:00 2001 From: Vexu Date: Fri, 15 May 2020 11:06:34 +0300 Subject: [PATCH 74/74] cleanup* remove unecessary error* properly handle ReturnTypeInvalid in ast.zig functions* assert that the tree is clean in render.zig* simplify parser recovery with top level decls --- lib/std/zig/ast.zig | 8 ++------ lib/std/zig/parse.zig | 38 +++++++++---------------------------- lib/std/zig/parser_test.zig | 5 ++--- lib/std/zig/render.zig | 3 +++ 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 351162bec0..b1441d5b25 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -166,7 +166,6 @@ pub const Error = union(enum) { ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap, ExpectedSuffixOp: ExpectedSuffixOp, DeclBetweenFields: DeclBetweenFields, - MissingComma: MissingComma, InvalidAnd: InvalidAnd, pub fn render(self: *const Error, tokens: *Tree.TokenList, stream: var) !void { @@ -217,7 +216,6 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream), .ExpectedSuffixOp => |*x| return x.render(tokens, stream), .DeclBetweenFields => |*x| return x.render(tokens, stream), - .MissingComma => |*x| return x.render(tokens, stream), .InvalidAnd => |*x| return x.render(tokens, stream), } } @@ -270,7 +268,6 @@ pub const Error = union(enum) { .ExpectedDerefOrUnwrap => |x| return x.token, .ExpectedSuffixOp => |x| return x.token, .DeclBetweenFields => |x| return x.token, - .MissingComma => |x| return x.token, .InvalidAnd => |x| return x.token, } } @@ -318,7 +315,6 @@ pub const Error = union(enum) { pub const ExtraVolatileQualifier = SimpleError("Extra volatile qualifier"); pub const ExtraAllowZeroQualifier = SimpleError("Extra allowzero qualifier"); pub const DeclBetweenFields = SimpleError("Declarations are not allowed between container fields"); - pub const MissingComma = SimpleError("Expected comma between items"); pub const InvalidAnd = SimpleError("`&&` is invalid. Note that `and` is boolean AND."); pub const ExpectedCall = struct { @@ -926,7 +922,7 @@ pub const Node = struct { if (i < 1) return node; i -= 1; }, - .Invalid => unreachable, + .Invalid => {}, } if (self.body_node) |body_node| { @@ -948,7 +944,7 @@ pub const Node = struct { if (self.body_node) |body_node| return body_node.lastToken(); switch (self.return_type) { .Explicit, .InferErrorSet => |node| return node.lastToken(), - .Invalid => unreachable, + .Invalid => |tok| return tok, } } }; diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 74945b1b33..a269dc616c 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -78,7 +78,7 @@ fn parseRoot(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error /// / KEYWORD_pub? ContainerField COMMA ContainerMembers /// / KEYWORD_pub? ContainerField /// / -fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!Node.Root.DeclList { +fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) !Node.Root.DeclList { var list = Node.Root.DeclList.init(arena); var field_state: union(enum) { @@ -136,7 +136,7 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree) All if (parseTopLevelDecl(arena, it, tree) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { - // try again + findNextContainerMember(it); continue; }, }) |node| { @@ -324,7 +324,7 @@ fn findNextStmt(it: *TokenIterator) void { } /// Eat a multiline container doc comment -fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) Allocator.Error!?*Node { +fn parseContainerDocComments(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { var lines = Node.DocComment.LineList.init(arena); while (eatToken(it, .ContainerDocComment)) |line| { try lines.push(line); @@ -384,7 +384,7 @@ fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?* /// <- (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) /// / (KEYWORD_export / KEYWORD_extern STRINGLITERALSINGLE?)? KEYWORD_threadlocal? VarDecl /// / KEYWORD_usingnamespace Expr SEMICOLON -fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*Node { +fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { var lib_name: ?*Node = null; const extern_export_inline_token = blk: { if (eatToken(it, .Keyword_export)) |token| break :blk token; @@ -397,13 +397,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? break :blk null; }; - if (parseFnProto(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - findNextContainerMember(it); - return error.ParseError; - }, - }) |node| { + if (try parseFnProto(arena, it, tree)) |node| { const fn_node = node.cast(Node.FnProto).?; fn_node.*.extern_export_inline_token = extern_export_inline_token; fn_node.*.lib_name = lib_name; @@ -413,7 +407,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? // since parseBlock only return error.ParseError on // a missing '}' we can assume this function was // supposed to end here. - error.ParseError => null, + error.ParseError => return node, }) |body_node| { fn_node.body_node = body_node; return node; @@ -437,14 +431,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? const thread_local_token = eatToken(it, .Keyword_threadlocal); - if (parseVarDecl(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - // try to skip to next decl - findNextContainerMember(it); - return error.ParseError; - }, - }) |node| { + if (try parseVarDecl(arena, it, tree)) |node| { var var_decl = node.cast(Node.VarDecl).?; var_decl.*.thread_local_token = thread_local_token; var_decl.*.comptime_token = null; @@ -469,14 +456,7 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!? return error.ParseError; } - return parseUse(arena, it, tree) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.ParseError => { - // try to skip to next decl - findNextContainerMember(it); - return error.ParseError; - }, - }; + return try parseUse(arena, it, tree); } /// FnProto <- KEYWORD_fn IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? LinkSection? EXCLAMATIONMARK? (KEYWORD_var / TypeExpr) @@ -2926,7 +2906,7 @@ fn ListParseFn(comptime L: type, comptime nodeParseFn: var) ParseFn(L) { // this is likely just a missing comma, // continue parsing this list and give an error try tree.errors.push(.{ - .MissingComma = .{ .token = it.index }, + .ExpectedToken = .{ .token = it.index, .expected_id = .Comma }, }); }, } diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index f92cc5a222..6adc44a5b7 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -32,8 +32,8 @@ test "recovery: missing comma" { \\ } \\} , &[_]Error{ - .MissingComma, - .MissingComma, + .ExpectedToken, + .ExpectedToken, .InvalidAnd, .InvalidToken, }); @@ -2983,7 +2983,6 @@ test "zig fmt: extern without container keyword returns error" { , &[_]Error{ .ExpectedExpr, .ExpectedVarDeclOrFn, - .ExpectedContainerMembers, }); } diff --git a/lib/std/zig/render.zig b/lib/std/zig/render.zig index 64f2f77f6c..9ca6d4450c 100644 --- a/lib/std/zig/render.zig +++ b/lib/std/zig/render.zig @@ -13,6 +13,9 @@ pub const Error = error{ /// Returns whether anything changed pub fn render(allocator: *mem.Allocator, stream: var, tree: *ast.Tree) (@TypeOf(stream).Error || Error)!bool { + // cannot render an invalid tree + std.debug.assert(tree.errors.len == 0); + // make a passthrough stream that checks whether something changed const MyStream = struct { const MyStream = @This();