Loop through all modules and module members?

Philippe Sigaud philippe.sigaud at gmail.com
Sat Jan 1 05:05:37 PST 2011


On Sat, Jan 1, 2011 at 11:14, bearophile <bearophileHUGS at lycos.com> wrote:
> %u:
>
>> I would like to perform compile-time reflection on a module (such as
>> enumerating all the classes inside the module) and/or on all modules in the
>> code -- are either of these possible? And if so, how?
>
> You may add your enhancement requests here, explaining why you need them:
> http://d.puremagic.com/issues/show_bug.cgi?id=4476
>
> At the moment the static reflection is not able to do everything. Listing all modules in the code looks like work for rmdm. Listing all classes in a module seems work for __traits/meta, plus a compile-time Filter.

Yes, it's doable :

template StaticFilter(alias Pred, T...)
{
    static if (T.length == 0)
        alias TypeTuple!() StaticFilter;
    else static if (Pred!(T[0]))
        alias TypeTuple!(T[0], StaticFilter!(Pred, T[1 .. $])) StaticFilter;
    else
        alias StaticFilter!(Pred, T[1 .. $]) StaticFilter;
}

template isClass(string name)
{
mixin("
      static if (is(" ~ name ~ " == class))
          enum bool isClass = true;
      else
        enum bool isClass = false;");
}

template extractClasses(string moduleName, members...)
{
    alias StaticFilter!(isClass,members) extractClasses;
}

template classMembers(string moduleName)
{
    mixin("alias extractClasses!(moduleName, __traits(allMembers, " ~
moduleName ~ ")) classMembers;");
}


if in module dir.mod1.d you have

class A {}
class B : A {}
struct S {}
class C {}
int foo() { return 0;}

then

classMembers!("dir.mod1") will become the tuple ("A", "B", "C") during
compilation.

It's buggy, though: the module needs to be in a directory. You cannot
do classMembers!("mod1"). Too bad.
Note that class templates are *not* classes. So most of std.* modules
will return an empty tuple, because they're full of templates.
Another detail I didn't have the time to correct: the names should be
tested fully qualified, to avoid any name clash with locally-defined
classes.

As for listing all modules imported by a module, I have something, but
it's not very elegant: it scans the text, looking for import
declarations. It works, but at runtime. I'm not sure it's doable at
compile-time right now: you need to have access to the module code, as
text. Do imports work in CT-evaluable functions?

Philippe


More information about the Digitalmars-d-learn mailing list