-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zig things #1
Comments
I spent a few hours thinking of a reasonable way of generating functions in comptime. Idea of how to create functions in comptimePrevious suggestions would have the comptime code create a string, then compile that using a builtin. How it would work (from a user's perspective)This is really two features: declarations in a comptime-generated type, and generating actual functions in comptime. First up, declarations in a comptime generated type. This is the easier of the two to explain, however it is probably the harder one to implement. A struct can have a list of fields, why not a list declarations? This would simply add a way for a declaration's value and publicity to be given when creating a struct, rather than just its name. const S = @Type(
std.builtin.Type{
.Struct = .{
// other info is hidden for reasier reading
.declarations = &[_]std.builtin.Type.Declaration {
.{
.name = "ADeclaration",
// The exact way through which the following three fields are filled out does not matter,
// Only that a way for the values of declarations can be created by code like this
.publicity = .public,
.type = comptime_int,
.value = 7,
},
}
}
}
)
test "hello" {
try testing.expectEqual(7, S.ADeclaration);
} Next, generating functions in comptime. This is a bit more complex, but still not too bad. Likely easier to implement, because it doesn't require changing a fundamental data structure. To generate a function, a new builtin, It takes a function's type information ( const std = @import("std");
const my_fn_type = fn(i32) i32;
const my_fn_info = @typeInfo(my_fn_type).Fn;
const myFn = @Fn(my_fn_info, {
//params is a tuple with all of the parameters
return args[0] + 20;
})
test "fn" {
std.testing.expectEqual(120, myFn(100));
} In the case of this library, it could be used to create the vtable wrapper functions, somewhat similar to this: // These would be local variables of the function that generates the wrapper functions
const fn_type = fn(Instance, i32) void;
const fn_info = @typeInfo(fn_type).Fn;
const function_name = "dynamicFunction";
const function = @Fn(function_info, {
// Pretend tuples can be sliced like this. In the real code, one could use an inline-for loop to build the tuple
const arguments_to_pass = args[1..];
const vtable_entry = @field(args[0].vtable, function_name);
@call(.auto, vtable_entry, arguments_to_pass);
}); These two features, when combined, would make it possible to take a list of functions and just straight up build the entire interface type in comptime |
There are a number of Zig related issues that make development and usage of this library quite difficult.
(Ordered roughly from most important to least important)
Annotating declarations:
In this library, in order to create an instance function that is not dynamically dispatched, the function must be prefixed with 'static_' so the
makeInterface
function can detect it. A better way to do it without using a prefix does not seem to exist at the moment, although some proposals (such as this one) might make this possible in the future.Circular Dependencies:
Due to the nature of how interfaces work, there is an extremely annoying tendency to create unavoidable circular dependencies. Some way to break them or at least alleviate them would be appreciated.
Note that I did create a workaround, which can be found in src/tests/circular_reference.zig
A way to detect inferred error sets:
The compiler crashes when trying to use an interface with inferred error sets. The solution is to use a defined error set, but that is not clear to people using this library without knowing that ahead of time. In order to create a better error message than "Oh no the compiler crashed", being able to detect if an error set is inferred would make that a lot better for users.
Creating functions:
Right now, the library still requires the user to create the vtable forward functions (which are used to create the vtable itself, which is part of why there are so many problems with circular dependencies). Some way to generate functions in comptime would be great.
I REALLY don't want to do any preprocessing of the user's code - that would make using this library quite a bit more difficult.
The text was updated successfully, but these errors were encountered: