Thread overview
Introspecting a Module with Traits, allMembers
Jul 09, 2014
NCrashed
Jul 09, 2014
Justin Whear
Jul 09, 2014
NCrashed
Jul 09, 2014
Dicebot
Jul 10, 2014
Adam D. Ruppe
July 09, 2014
Hello,

I'm looking to introspect a module, list all the members, iterate over them and filter them by kind inside of a static constructor. This is in the hope of shortening some hand-written code that is quite repetitive (adding many struct instances to an associative array in a static constructor).

The code I'm trying to improve upon can be seen here:
https://github.com/maximecb/Higgs/blob/master/source/ir/iir.d#L56

I've done some googling, and it seems I should be able to use the allMembers trait (http://wiki.dlang.org/Finding_all_Functions_in_a_Module), but unfortunately, the module name seems to be unrecognized, no matter which way I spell it:

auto members = [__traits(allMembers, "ir.ir")];
pragma(msg, members);

Produces:
ir/iir.d(85): Error: argument has no members

Other people seem to have run into this problem. Am I doing it wrong or is this a bug in DMD?
July 09, 2014
On Wednesday, 9 July 2014 at 20:04:47 UTC, Maxime Chevalier-Boisvert wrote:
> auto members = [__traits(allMembers, "ir.ir")];
> pragma(msg, members);

Have you tried without quotes?
pragma(msg, __traits(allMembers, ir.ir));
July 09, 2014
On Wed, 09 Jul 2014 20:07:56 +0000, NCrashed wrote:

> On Wednesday, 9 July 2014 at 20:04:47 UTC, Maxime Chevalier-Boisvert wrote:
>> auto members = [__traits(allMembers, "ir.ir")];
>> pragma(msg, members);
> 
> Have you tried without quotes?
> pragma(msg, __traits(allMembers, ir.ir));

Also, looks like it should be "ir.iir"
July 09, 2014
On Wednesday, 9 July 2014 at 20:07:57 UTC, NCrashed wrote:
> Produces:
> ir/iir.d(85): Error: argument has no members

If module name is ir.iir: pragma(msg, __traits(allMembers, ir.iir));
July 09, 2014
On Wednesday, 9 July 2014 at 20:07:57 UTC, NCrashed wrote:
> On Wednesday, 9 July 2014 at 20:04:47 UTC, Maxime Chevalier-Boisvert wrote:
>> auto members = [__traits(allMembers, "ir.ir")];
>> pragma(msg, members);
>
> Have you tried without quotes?
> pragma(msg, __traits(allMembers, ir.ir));

Did need to write it without the quotes, and to add "enum" to force compile-time evaluation. It's actually ir.ops that I wanted to list the members of. Got the following snippet to work:

static this()
{
    enum members = [__traits(allMembers, ir.ops)];
    pragma(msg, members);
}

Prints:
["object", "ir", "jit", "OpArg", "OpInfo", "Opcode", "GET_ARG", "SET_STR", "MAKE_VALUE", "GET_WORD", "GET_TYPE", "IS_I32", ...]
July 09, 2014
I got the following code to do what I want:

static this()
{
    void addOp(ref Opcode op)
    {
        assert (
            op.mnem !in iir,
            "duplicate op name " ~ op.mnem
        );

        iir[op.mnem] = &op;
    }

    foreach (memberName; __traits(allMembers, ir.ops))
    {
        static if (__traits(compiles, addOp(__traits(getMember, ir.ops, memberName))))
        {
            writeln(memberName);
            addOp(__traits(getMember, ir.ops, memberName));
        }
    }
}


It's a bit of a hack, but it works. Is there any way to create some sort of alias for __traits(getMember, ir.ops, memberName) so that I don't have to write it out in full twice? Made some attempts but only got the compiler to complain.
July 09, 2014
On Wednesday, 9 July 2014 at 20:52:29 UTC, Maxime Chevalier-Boisvert wrote:
> It's a bit of a hack, but it works. Is there any way to create some sort of alias for __traits(getMember, ir.ops, memberName) so that I don't have to write it out in full twice? Made some attempts but only got the compiler to complain.

alias Alias(alias Sym) = Sym;
alias member = Alias!(__traits(getMember, ir.ops, memberName);

It does not work with normal alias because of grammar limitation afaik.
July 10, 2014
The others have already given some answers, I just want to point out that the (free) sample chapter of my D book covers this topic too: http://www.packtpub.com/discover-advantages-of-programming-in-d-cookbook/book

Scanning a whole module and getting everything out takes a few tricks that I talk about in there.