#Comptime Code Inclusion
1 messages · Page 1 of 1 (latest)
as far as i know you can only do it by declaring fields Conditionally available, by doing it like this const thing = if (true) enum { one, two, three, four, five, six, seven, } else enum { one, two, three, six, seven, };
that's what I feared. Thank you!
Did you need it for something specific ?
I'm making an enum for #defines in a c header:
#define PREFIX_ONE 1
#define PREFIX_TWO 2
#define PREFIX_THREE 3
#ifdef SOME_CONDITION
#define PREFIX_FOUR 4
#define PREFIX_FIVE 5
#endif /* SOME_CONDITION */
#define PREFIX_SIX 6
#define PREFIX_SEVEN 7
so it is a project that uses c and zig?
it's bindings for a c project
maybe something like this?
PREFIX_ONE = 1,
PREFIX_TWO = 2,
PREFIX_THREE = 3,
PREFIX_FOUR = if(truthy) 4 else undefined,
PREFIX_FIVE = if(truthy) 5 else undefined,
PREFIX_SIX = 6,
PREFIX_SEVEN = 7
};```
yeah, but I thought he could check if they were undefined and then trow error
I thought about this but the risk is too high that the user tries to use them, when the compilation options don't support it
it just means "don't assign a value", meaning, let it be whatever garbage value was already there
oh yeah
forgot that part
at any rate, if you don't want the duplication, you could write with @Type
say what now
is there a way to generate an enum at comptime such that you can call type.add("four", 4) or something?
and do it that way?
not arbitrarily
but you can do so imperatively in a specific scope
typing up an example
const Thing = @Type(.{ .Enum = blk: {
const fields = [_]EnumField{
enumField("one", 1),
enumField("two", 2),
enumField("three", 3),
} ++ (if (some_condition) [_]EnumField{
enumField("four", 4),
enumField("five", 5),
} else [_]EnumField{}) ++ [_]EnumField{
enumField("six", 6),
enumField("seven", 7),
};
break :blk .{
.tag_type = std.meta.IntFittingRange(1, 7),
.is_exhaustive = true,
.decls = &.{},
.fields = &fields,
};
} });
// for convenience
const EnumField = std.builtin.Type.EnumField;
inline fn enumField(comptime name: []const u8, value: comptime_int) EnumField {
return .{ .name = name, .value = value };
}
there's other ways you can write this
oh that's great, I didn't know that was possible
e.g. you could declare var fields: []const EnumField = &.{}; and imperatively concatenate only the fields you need fields = fields ++ &[_]EnumField{ .{ .name = "foo", .value = 3 } };
I think I'll go with your second suggestion, probably will look a little nicer
Thank you so much @olive pollen and @hushed shard !
you could also write a utility function that makes it look nicer
you're welcome, i'm sry i couldn't do more
const Thing = ConditionalEnumFields(.{
.one = true,
.two = true,
.three = true,
.four = some_condition,
.five = some_condition,
.six = true,
.seven = true,
});
fn ConditionalEnumFields(comptime field_bools: anytype) type {
const field_infos = @typeInfo(@TypeOf(field_bools)).Struct.fields;
var fields: []const std.builtin.Type.EnumField = &.{};
for (field_infos, 0..) |field, i| {
if (!@field(field_bools, field.name)) continue;
fields = fields ++ &[_]std.builtin.Type.EnumField{.{
.name = field.name,
.value = i,
}};
}
return @Type(.{ .Enum = .{
.tag_type = std.meta.IntFittingRange(0, field_infos.len - 1),
.is_exhaustive = true,
.decls = &.{},
.fields = fields,
} });
}
galaxy brain
I shall be taking this
didn't test it at all, might have some errors
also caveat: ZLS will not be able to autocomplete this
and the enum will not be able to have methods
that is fine for these purposes
i just tested the code and fixed some thing ```zig fn ConditionalEnumFields(comptime field_bools: anytype) type {
const field_infos = @typeInfo(@TypeOf(field_bools)).Struct.fields;
var fields: []const std.builtin.Type.EnumField = &.{};
for (field_infos, 0..) |field, i| {
if (!@field(field_bools, field.name)) continue;
fields = fields ++ &[_]std.builtin.Type.EnumField{.{
.name = field.name,
.value = i,
}};
}
return @Type(.{ .Enum = .{ .tag_type = std.math.IntFittingRange(0, field_infos.len - 1), .fields = fields, .decls = &.{}, .is_exhaustive = true } });
}``` Please be welcome to correct me if you find any errors in the code
note: you can put a comma after .is_exhaustive = true and have zig fmt split it over multiple lines
what did you fix?
ah the array syntax
good catch
- std.meta.IntFittingRange doesn't exist
righto
so i changed it to std.math.IntFittingRange
always get that one confused