From 3526f5fb84b89b6327fc21c6b836b842bf4db90d Mon Sep 17 00:00:00 2001 From: nullptrdevs <16590917+nullptrdevs@users.noreply.github.com> Date: Wed, 14 Dec 2022 17:58:38 -0800 Subject: [PATCH] Zig @call changes (#822) First parameter is now a `std.builtin.CallModifier`. --- build.zig | 2 +- src/data/generate-data.py | 0 src/data/master.zig | 72 ++++----------------------------------- src/inlay_hints.zig | 2 +- src/semantic_tokens.zig | 2 +- src/translate_c.zig | 2 +- 6 files changed, 11 insertions(+), 69 deletions(-) mode change 100644 => 100755 src/data/generate-data.py diff --git a/build.zig b/build.zig index 971ed16..29926d9 100644 --- a/build.zig +++ b/build.zig @@ -6,7 +6,7 @@ const zls_version = std.builtin.Version{ .major = 0, .minor = 11, .patch = 0 }; pub fn build(b: *std.build.Builder) !void { const current_zig = builtin.zig_version; - const min_zig = std.SemanticVersion.parse("0.11.0-dev.715+cffbb32d3") catch return; // Deprecated ascii symbols removed + const min_zig = std.SemanticVersion.parse("0.11.0-dev.780+6378644d4") catch return; // Changes to @call if (current_zig.order(min_zig).compare(.lt)) @panic(b.fmt("Your Zig version v{} does not meet the minimum build requirement of v{}", .{ current_zig, min_zig })); const target = b.standardTargetOptions(.{}); diff --git a/src/data/generate-data.py b/src/data/generate-data.py old mode 100644 new mode 100755 diff --git a/src/data/master.zig b/src/data/master.zig index 9eacf7b..c5f45b4 100644 --- a/src/data/master.zig +++ b/src/data/master.zig @@ -79,24 +79,6 @@ pub const builtins = [_]Builtin{ "expression", }, }, - .{ - .name = "@asyncCall", - .signature = "@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: anytype) anyframe->T", - .snippet = "@asyncCall(${1:frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8}, ${2:result_ptr}, ${3:function_ptr}, ${4:args: anytype})", - .documentation = - \\`@asyncCall` performs an `async` call on a function pointer, which may or may not be an [async function](https://ziglang.org/documentation/master/#Async-Functions). - \\ - \\The provided `frame_buffer` must be large enough to fit the entire function frame. This size can be determined with [@frameSize](https://ziglang.org/documentation/master/#frameSize). To provide a too-small buffer invokes safety-checked [Undefined Behavior](https://ziglang.org/documentation/master/#Undefined-Behavior). - \\ - \\`result_ptr` is optional ([null](https://ziglang.org/documentation/master/#null) may be provided). If provided, the function call will write its result directly to the result pointer, which will be available to read after [await](https://ziglang.org/documentation/master/#Async-and-Await) completes. Any result location provided to `await` will copy the result from `result_ptr`.

{#code_begin|test|async_struct_field_fn_pointer#} {#backend_stage1#} const std = @import("std"); const expect = std.testing.expect; test "async fn pointer in a struct field" { var data: i32 = 1; const Foo = struct { bar: fn (*i32) callconv(.Async) void, }; var foo = Foo{ .bar = func }; var bytes: [64]u8 align(@alignOf(@Frame(func))) = undefined; const f = @asyncCall(&bytes, {}, foo.bar, .{&data}); try expect(data == 2); resume f; try expect(data == 4); } fn func(y: *i32) void { defer y.* += 2; y.* += 1; suspend {} }` - , - .arguments = &.{ - "frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8", - "result_ptr", - "function_ptr", - "args: anytype", - }, - }, .{ .name = "@atomicLoad", .signature = "@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T", @@ -291,8 +273,8 @@ pub const builtins = [_]Builtin{ }, .{ .name = "@call", - .signature = "@call(options: std.builtin.CallOptions, function: anytype, args: anytype) anytype", - .snippet = "@call(${1:options: std.builtin.CallOptions}, ${2:function: anytype}, ${3:args: anytype})", + .signature = "@call(modifier: std.builtin.CallModifier, function: anytype, args: anytype) anytype", + .snippet = "@call(${1:modifier: std.builtin.CallModifier}, ${2:function: anytype}, ${3:args: anytype})", .documentation = \\Calls a function, in the same way that invoking an expression with parentheses does: \\ @@ -300,7 +282,7 @@ pub const builtins = [_]Builtin{ \\const expect = @import("std").testing.expect; \\ \\test "noinline function call" { - \\ try expect(@call(.{}, add, .{3, 9}) == 12); + \\ try expect(@call(.auto, add, .{3, 9}) == 12); \\} \\ \\fn add(a: i32, b: i32) i32 { @@ -308,10 +290,10 @@ pub const builtins = [_]Builtin{ \\} \\``` \\ - \\`@call` allows more flexibility than normal function call syntax does. The `CallOptions` struct is reproduced here:

{#syntax_block|zig|builtin.CallOptions struct#} pub const CallOptions = struct { modifier: Modifier = .auto, /// Only valid when `Modifier` is `Modifier.async_kw`. stack: ?[]align(std.Target.stack_align) u8 = null, pub const Modifier = enum { /// Equivalent to function call syntax. auto, /// Equivalent to async keyword used with function call syntax. async_kw, /// Prevents tail call optimization. This guarantees that the return /// address will point to the callsite, as opposed to the callsite's /// callsite. If the call is otherwise required to be tail-called /// or inlined, a compile error is emitted instead. never_tail, /// Guarantees that the call will not be inlined. If the call is /// otherwise required to be inlined, a compile error is emitted instead. never_inline, /// Asserts that the function call will not suspend. This allows a /// non-async function to call an async function. no_async, /// Guarantees that the call will be generated with tail call optimization. /// If this is not possible, a compile error is emitted instead. always_tail, /// Guarantees that the call will inlined at the callsite. /// If this is not possible, a compile error is emitted instead. always_inline, /// Evaluates the call at compile-time. If the call cannot be completed at /// compile-time, a compile error is emitted instead. compile_time, }; }; {#end_syntax_block#} + \\`@call` allows more flexibility than normal function call syntax does. The `CallModifier` enum is reproduced here:

{#syntax_block|zig|builtin.CallModifier struct#} pub const CallModifier = enum { /// Equivalent to function call syntax. auto, /// Equivalent to async keyword used with function call syntax. async_kw, /// Prevents tail call optimization. This guarantees that the return /// address will point to the callsite, as opposed to the callsite's /// callsite. If the call is otherwise required to be tail-called /// or inlined, a compile error is emitted instead. never_tail, /// Guarantees that the call will not be inlined. If the call is /// otherwise required to be inlined, a compile error is emitted instead. never_inline, /// Asserts that the function call will not suspend. This allows a /// non-async function to call an async function. no_async, /// Guarantees that the call will be generated with tail call optimization. /// If this is not possible, a compile error is emitted instead. always_tail, /// Guarantees that the call will inlined at the callsite. /// If this is not possible, a compile error is emitted instead. always_inline, /// Evaluates the call at compile-time. If the call cannot be completed at /// compile-time, a compile error is emitted instead. compile_time, }; {#end_syntax_block#} , .arguments = &.{ - "options: std.builtin.CallOptions", + "modifier: std.builtin.CallModifier", "function: anytype", "args: anytype", }, @@ -770,30 +752,6 @@ pub const builtins = [_]Builtin{ "float: anytype", }, }, - .{ - .name = "@frame", - .signature = "@frame() *@Frame(func)", - .snippet = "@frame()", - .documentation = - \\This function returns a pointer to the frame for a given function. This type can be [coerced](https://ziglang.org/documentation/master/#Type-Coercion) to `anyframe->T` and to `anyframe`, where `T` is the return type of the function in scope. - \\ - \\This function does not mark a suspension point, but it does cause the function in scope to become an [async function](https://ziglang.org/documentation/master/#Async-Functions). - , - .arguments = &.{}, - }, - .{ - .name = "@Frame", - .signature = "@Frame(func: anytype) type", - .snippet = "@Frame(${1:func: anytype})", - .documentation = - \\This function returns the frame type of a function. This works for [Async Functions](https://ziglang.org/documentation/master/#Async-Functions) as well as any function without a specific calling convention. - \\ - \\This type is suitable to be used as the return type of [async](https://ziglang.org/documentation/master/#Async-and-Await) which allows one to, for example, heap-allocate an async function frame:

{#code_begin|test|heap_allocated_frame#} {#backend_stage1#} const std = @import("std"); test "heap allocated frame" { const frame = try std.heap.page_allocator.create(@Frame(func)); frame.* = async func(); } fn func() void { suspend {} }` - , - .arguments = &.{ - "func: anytype", - }, - }, .{ .name = "@frameAddress", .signature = "@frameAddress() usize", @@ -807,25 +765,12 @@ pub const builtins = [_]Builtin{ , .arguments = &.{}, }, - .{ - .name = "@frameSize", - .signature = "@frameSize(func: anytype) usize", - .snippet = "@frameSize(${1:func: anytype})", - .documentation = - \\This is the same as `@sizeOf(@Frame(func))`, where `func` may be runtime-known. - \\ - \\This function is typically used in conjunction with [@asyncCall](https://ziglang.org/documentation/master/#asyncCall). - , - .arguments = &.{ - "func: anytype", - }, - }, .{ .name = "@hasDecl", .signature = "@hasDecl(comptime Container: type, comptime name: []const u8) bool", .snippet = "@hasDecl(${1:comptime Container: type}, ${2:comptime name: []const u8})", .documentation = - \\Returns whether or not a [struct](https://ziglang.org/documentation/master/#struct), [enum](https://ziglang.org/documentation/master/#enum), or [union](https://ziglang.org/documentation/master/#union) has a declaration matching `name`.

{#code_begin|test|hasDecl#} const std = @import("std"); const expect = std.testing.expect; const Foo = struct { nope: i32, pub var blah = "xxx"; const hi = 1; }; test "@hasDecl" { try expect(@hasDecl(Foo, "blah")); // Even though `hi` is private, @hasDecl returns true because this test is // in the same file scope as Foo. It would return false if Foo was declared // in a different file. try expect(@hasDecl(Foo, "hi")); // @hasDecl is for declarations; not fields. try expect(!@hasDecl(Foo, "nope")); try expect(!@hasDecl(Foo, "nope1234")); }` + \\Returns whether or not a [container](https://ziglang.org/documentation/master/#Containers) has a declaration matching `name`.

{#code_begin|test|hasDecl#} const std = @import("std"); const expect = std.testing.expect; const Foo = struct { nope: i32, pub var blah = "xxx"; const hi = 1; }; test "@hasDecl" { try expect(@hasDecl(Foo, "blah")); // Even though `hi` is private, @hasDecl returns true because this test is // in the same file scope as Foo. It would return false if Foo was declared // in a different file. try expect(@hasDecl(Foo, "hi")); // @hasDecl is for declarations; not fields. try expect(!@hasDecl(Foo, "nope")); try expect(!@hasDecl(Foo, "nope1234")); }` , .arguments = &.{ "comptime Container: type", @@ -1721,16 +1666,13 @@ pub const builtins = [_]Builtin{ \\ - [Error Union Type](https://ziglang.org/documentation/master/#Error-Union-Type) \\ - [Vectors](https://ziglang.org/documentation/master/#Vectors) \\ - [opaque](https://ziglang.org/documentation/master/#opaque) - \\ - [@Frame](https://ziglang.org/documentation/master/#Frame) \\ - `anyframe` \\ - [struct](https://ziglang.org/documentation/master/#struct) \\ - [enum](https://ziglang.org/documentation/master/#enum) \\ - [Enum Literals](https://ziglang.org/documentation/master/#Enum-Literals) \\ - [union](https://ziglang.org/documentation/master/#union) \\ - \\For these types, `@Type` is not available: - \\ - [Functions](https://ziglang.org/documentation/master/#Functions) - \\ - BoundFn + \\`@Type` is not available for [Functions](https://ziglang.org/documentation/master/#Functions). , .arguments = &.{ "comptime info: std.builtin.Type", diff --git a/src/inlay_hints.zig b/src/inlay_hints.zig index 4c2481c..94b66fe 100644 --- a/src/inlay_hints.zig +++ b/src/inlay_hints.zig @@ -251,7 +251,7 @@ fn callWriteNodeInlayHint(allocator: std.mem.Allocator, args: anytype) error{Out // return await @asyncCall(child_frame, {}, writeNodeInlayHint, args); // } else { // TODO find a non recursive solution - return @call(.{}, writeNodeInlayHint, args); + return @call(.auto, writeNodeInlayHint, args); // } } diff --git a/src/semantic_tokens.zig b/src/semantic_tokens.zig index d54464f..4257292 100644 --- a/src/semantic_tokens.zig +++ b/src/semantic_tokens.zig @@ -276,7 +276,7 @@ fn callWriteNodeTokens(allocator: std.mem.Allocator, args: anytype) WriteTokensE return await @asyncCall(child_frame, {}, writeNodeTokens, args); } else { // TODO find a non recursive solution - return @call(.{}, writeNodeTokens, args); + return @call(.auto, writeNodeTokens, args); } } diff --git a/src/translate_c.zig b/src/translate_c.zig index dcc7a31..d58dca3 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -52,7 +52,7 @@ fn callConvertCIncludeInternal(allocator: std.mem.Allocator, args: anytype) erro return await @asyncCall(child_frame, {}, convertCIncludeInternal, args); } else { // TODO find a non recursive solution - return @call(.{}, convertCIncludeInternal, args); + return @call(.auto, convertCIncludeInternal, args); } }