#is it possible to add fields to a enum dynamically?
1 messages ยท Page 1 of 1 (latest)
hi thanks, could you give me an example or a link?
i guess what i have now is a comptime version, and with a worse and verbose
form: https://github.com/haolian9/viz/blob/dev/profiles.zig
Yea
i had wrote it two months ago, and i still have no idea to simplify it, hehe
Dunno if this works
but
something along this lines
fn GetEnum(someEnum: type) type {
var fields: []const std.builtin.Type.EnumField = std.meta.fields(someEnum);
var counter = fields.len;
inline for (std.meta.fields(someEnum)) |x, i| {
inline for (std.meta.fields(someEnum)[i..]) |y, j| {
fields = fields ++ std.builtin.Type.EnumField{ .name = x.name ++ y.name, .value = counter };
}
}
var enumInfo = @typeInfo(someEnum);
return @TypeOf(std.builtin.Type.Enum{
.layout = enumInfo.Enum.layout,
.tag_type = std.math.IntFittingRange(0, fields.len),
.fields = fields,
.decls = &.{},
.is_exhaustive = true,
});
}
wow, never thought zig can do like that!
thank you for the direction, i will try it.
Yeah, the code might be bad btw
I am not testing this
lol
but something along this lines it is
append line should be fields = fields ++ &[1]std.builtin.Type.EnumField{ .{ .name = ... } } I think? Or can you append a single element like that and I never realised?
You are right, I think that's the error
tho you can do &.{} and using an @as too
lol
no worries, the direction is enough for me. i'll learn it by tests
iirc it doesn't work nicely without the type annotated somewhere, was doing stuff with it just the other day
so figured I'd just annotate on the outside
Oh right yeah
@as(your_ptr_type, &.{something});
thank you all!
Other error I am seeing now
You need to make the union lol
@Type(.{ .Enum = std.builtin.Type.Enum{
.layout = enumInfo.Enum.layout,
.tag_type = std.math.IntFittingRange(0, fields.len),
.fields = fields,
.decls = &.{},
.is_exhaustive = true,
} })```
and is @Type lol
Yeah not sleeping makes me slow
fn GetEnum(comptime someEnum: type) type {
var fields: []const std.builtin.Type.EnumField = std.meta.fields(someEnum);
var counter = fields.len;
inline for (std.meta.fields(someEnum)) |x, i| {
inline for (std.meta.fields(someEnum)[i + 1 ..]) |y| {
fields = fields ++ @as([]const std.builtin.Type.EnumField, &.{std.builtin.Type.EnumField{ .name = x.name ++ y.name, .value = counter }});
counter += 1;
}
}
var enumInfo = @typeInfo(someEnum);
return @Type(.{ .Enum = std.builtin.Type.Enum{
.layout = enumInfo.Enum.layout,
.tag_type = std.math.IntFittingRange(0, fields.len),
.fields = fields,
.decls = &.{},
.is_exhaustive = true,
} });
}
@round folio
this works
just tested it
const SomeEnum = enum {
a,
b,
c,
};
/// Some other will have: a, b, c, ab, ac, bc
const SomeOther = GetEnum(SomeEnum);
yeah, works like a charm.
const Mode = GetEnum(enum { x, r, w });
pub fn main() !void {
print("{d} {d}", .{ @enumToInt(Mode.x), @enumToInt(Mode.rw) });
}
is this not best solved with bitwise flags? If you want to check for r you now have to check against multiple enums
Depends on objective
You can make this code ignore certain combinations
or you can make a enumSet for example
i guess i certainly can do some magic when generating these fields, so it isnt
a problem to this approach
yeah, but rwx are flags, so why go through all these hoops

Maybe they are experimenting
I think packed structs are better for flags for example
yeah those are nice
you could use with this now, EnumFieldStruct (std.enums.EnumFieldStruct)
Which generates a struct that have booleans for example
I think std prefers packed structs for flags in a lot of places now
Haven't seen them ๐
pub const DllFlags = packed struct {
stuff like that
There are still a bunch of methods that fit better or worse depending on how you wanna present it
yeah, just felt wrong to use a bunch metaprogramming enums for this, but dunno the context
fair
yeah, this approach is a bit complicated than my lua impl: https://github.com/haolian9/zongzi/blob/master/nvim/.config/nvim/lua/profiles.lua
but it's ok to me
People in this thread have answered how but never asked why :)
In Zig, you'd normally do this differently
Instead of a flags enum with r, w, x, rw, etc, you'd use a flags struct
๐ you can do this from the enum
const Mode = packed struct {
read: bool = false,
write: bool = false,
execute: bool = false,
};```
or you can do it manually
both ways are valid
and both ways will result in similar code
Ah yeah this was discussed, missed that
(not on asm ofc)