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

Reply via email to