Can Metaprogramming Help Here?
H. S. Teoh
hsteoh at quickfur.ath.cx
Fri Feb 26 20:42:50 UTC 2021
On Fri, Feb 26, 2021 at 11:37:18AM -0800, H. S. Teoh via Digitalmars-d-learn wrote:
> On Wed, Feb 24, 2021 at 08:10:30PM +0000, Mike Brown via Digitalmars-d-learn wrote:
> [...]
> > Thank you for the reply. Im struggling extending this to get the
> > nesting working.
[...]
Alright, here's an actual working example. Instead of using classes, I
decided to use templates instead, but the underlying concept is the
same:
-------------------------------------snip--------------------------------------
template branch(string _ident, _values...) {
enum ident = _ident;
alias values = _values;
}
// I used strings for easier concatenation to code, otherwise we have to use
// std.conv to convert it which is slow in CTFE.
static immutable string[] primes = [
"2", "3", "5", "7", "11", "13", "17", "19", "23", "29", "31", "37",
"41", // fill in more if you need to
];
string genPrimeId(size_t[] indices)
in (indices.length > 0)
{
string result = primes[indices[0]];
foreach (i; indices[1 .. $]) {
result ~= "*" ~ primes[i];
}
return result;
}
template primeIdsImpl(size_t[] indices, Args...)
if (indices.length > 0 && Args.length > 0)
{
static if (Args.length == 1) {
static if (is(typeof(Args[0]) == string)) {
enum primeIdsImpl = Args[0] ~ "=" ~ genPrimeId(indices) ~ ",\n";
} else {
enum primeIdsImpl = Args[0].ident ~ "=" ~ genPrimeId(indices) ~ ",\n" ~
primeIdsImpl!(indices ~ [ indices[$-1] + 1 ],
Args[0].values);
}
} else {
enum primeIdsImpl = primeIdsImpl!(indices, Args[0]) ~
primeIdsImpl!(indices[0 .. $-1] ~ [ indices[$-1] + 1 ],
Args[1 .. $]);
}
}
template primeIds(string enumName, Args...) if (Args.length > 0) {
enum primeIds = "enum " ~ enumName ~ " {\n" ~
primeIdsImpl!([0], Args) ~
"}";
}
mixin(primeIds!("token_type",
"endOfFile",
"unknown",
"newline",
branch!("identifier",
"userDefined",
"var",
"uses",
"constructor",
"do_",
"end_",
),
branch!("operator",
"copyAssignment",
),
));
void main() {
import std;
writefln("%s", token_type.identifier);
writefln("%d", token_type.identifier);
}
-------------------------------------snip--------------------------------------
You can change the mixin line to `pragma(msg, ...)` instead to see the
generated code string.
I noticed that the definitions of the first nested identifiers are
different from your original post; I don't know if this is a
misunderstanding on my side or an oversight on your part? After
identifier=7, the next prime should be 11, not 13, so userDefined should
start with 11*identifier rather than 13*identifier.
T
--
Shin: (n.) A device for finding furniture in the dark.
More information about the Digitalmars-d-learn
mailing list