Can Metaprogramming Help Here?

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Feb 26 19:37:18 UTC 2021


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.
> 
> 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?
[...]

Ah, so sorry, I completely overlooked the nesting part.  PrimeEnum as I
defined it in my first reply does not handle this at all, so it will
need to be extended.

Since we're dealing with a tree structure here, I think the best way is
to express the tree structure explicitly in a compile-time data
structure. Thanks to CTFE, this works pretty much exactly the same as
normal runtime data structures; the only difference is that they will be
processed at compile-time.

Here's a rough sketch of how I'd do it:

	class Entry {
		string ident;
		Entry[] subentries;
		this(string _id, Entry[] _subs = []) {
			ident = _id;
			subentries = _subs;
		}
	}

	Entry[] makeIdentTrees() {
		return [
			new Entry("endOfFile"),
			new Entry("unknown"),
			new Entry("newline"),
			new Entry("identifier", [
				new Entry("userDefined"),
				new Entry("var"),
				new Entry("uses"),
				... // you get the idea
			],
			new Entry("operator", [
				new Entry("copyAssignment"),
				... // etc.
			]));
		]
	}

You'd then write a recursive function that traverses this tree, using a
compile-time array of prime numbers, and compute the enum values that
way.  Format that into D code as a string, and use mixin to actually
create the enum.  The function can be written just like any runtime D
code, as long as it does not use any CTFE-incompatible language
features.

	string genEnum(Entry[] entries) {
		string code;
		... // traverse tree and generate D code here
		return code;
	}

	// Create the enum
	mixin(genEnum(makeIdentTrees()));


T

-- 
A mathematician learns more and more about less and less, until he knows everything about nothing; whereas a philospher learns less and less about more and more, until he knows nothing about everything.


More information about the Digitalmars-d-learn mailing list