Hello everyone, I’m having some trouble figuring out how to create (if possible) a declaration for a struct/union/enum using comptime
and metaprogramming. In other words:
How to, programmatically, create a function/declaration that translates to:
const Foo = struct {
pub fn bar() void {}
}
I’ve found this post asking a similar (maybe the same) question, that suggests wrapping the struct/union/enum in another struct/union/enum. Is this the only solution?
My use case is the following:
I’m initializing a enum
(Tokens
) and a StaticStringMap
(TokensMap
) using a const variable (_tokens
), so I can add/remove fields from one place and have the enum
and the StringMap
automatically updated.
const _tokens = [_][2][:0]const u8{
// (K,V) pairs
.{ "+", "plus" },
.{ "-", "minus" },
};
const Tokens = b: {
var enum_fields: [_tokens.len]std.builtin.Type.EnumField = undefined;
var i: u8 = 0;
for (&enum_fields, _tokens) |*enum_field, token| {
enum_field.* = .{ .name = token[1], .value = i };
i += 1;
}
break :b @Type(.{ .Enum = .{
.decls = &.{},
.fields = &enum_fields,
.tag_type = u8,
.is_exhaustive = false,
} });
};
const TokensMap = b: {
var map_kvs: [_tokens.len]struct { [:0]const u8, Tokens } = undefined;
var i: u8 = 0;
for (&map_kvs, _tokens) |*map_kv, token| {
map_kv.* = .{ token[0], @enumFromInt(i) };
i += 1;
}
break :b std.StaticStringMap(Tokens).initComptime(map_kvs);
};
The code behaves as intended, but I want _tokens
and TokensMap
only present in the enum
(Tokens
) scope, and expose functions from the enum
itself, so instead of calling TokensMap.has()
I can call Tokens.has()
, for example.