www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Introspecting a Module with Traits, allMembers

reply "Maxime Chevalier-Boisvert" <maximechevalierb gmail.com> writes:
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?
Jul 09 2014
next sibling parent reply "NCrashed" <NCrashed gmail.com> writes:
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));
Jul 09 2014
next sibling parent Justin Whear <justin economicmodeling.com> writes:
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"
Jul 09 2014
prev sibling next sibling parent "NCrashed" <NCrashed gmail.com> writes:
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));
Jul 09 2014
prev sibling parent reply "Maxime Chevalier-Boisvert" <maximechevalierb gmail.com> writes:
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", ...]
Jul 09 2014
parent reply "Maxime Chevalier-Boisvert" <maximechevalierb gmail.com> writes:
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.
Jul 09 2014
parent "Dicebot" <public dicebot.lv> writes:
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.
Jul 09 2014
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Jul 10 2014