On Tuesday, 23 February 2021 at 22:55:53 UTC, H. S. Teoh wrote:
On Tue, Feb 23, 2021 at 10:24:50PM +0000, Mike Brown via
Digitalmars-d-learn wrote:
Hi all,
Im porting some C++ code, which has a mess of a section that
implements prime number type id's. I've had to smother it to
death with test cases to get it reliable, I think
metaprogramming that D provides is the better solution - Id
rather not reimplement that C++ mess ideally.
Try something like this:
-----------------------------snip-----------------------------
import std;
int[] firstNPrimes(int n) {
// FIXME: replace this with actual primes computation
return [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 ];
}
string genEnum(string enumName, idents...)() {
string code = "enum " ~ enumName ~ " {";
auto primes = firstNPrimes(idents.length);
foreach (i, ident; idents) {
code ~= ident ~ " = " ~ primes[i].to!string ~ ", ";
}
code ~= "}";
return code;
}
template PrimeEnum(idents...) {
mixin(genEnum!("PrimeEnum", idents));
}
alias MyEnum = PrimeEnum!(
"unknown", "newline", "identifier", "var", "user_defined",
);
void main() {
writefln("%(%d\n%)", [
MyEnum.unknown,
MyEnum.newline,
MyEnum.identifier,
MyEnum.var,
MyEnum.user_defined
]);
}
-----------------------------snip-----------------------------
You can substitute the body of firstNPrimes with any standard
prime-generation algorithm. As long as it's not too
heavyweight, you should be able to get it to compile without
the compiler soaking up unreasonable amounts of memory. :-D If
you find the compiler using up too much memory, try
precomputing the list of primes beforehand and pasting it into
firstNPrimes (so that the CTFE engine doesn't have to recompute
it every time you compile).
Note that PrimeEnum can be used to generate any number of enums
you wish to have prime values. Or if you replace the call to
firstNPrimes with something else, you can generate enums whose
identifiers map to any integer sequence of your choosing.
T
Hi T,
Thank you for the reply. Im struggling extending this to get the
nesting working.
I'm trying something like:
string entry(string i, string[] inherit = []) {
return i;
}
alias token_type2 = PrimeEnum!(
entry("unknown"),
entry("newline"),
entry("identifier"),
entry("var", ["identifier"]),
entry("userDefined", ["identifier"])
);
Its worth noting that multiple inherited bases are needed too.
But I can't get those functions contexts linking, can I pass a
function pointer as lazy into the PrimeEnum!() template?
Would it be easier to just parse the text at once into a single
templating function?
Kind regards,
Mike Brown