www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Detecting alias declarations - the dodgy way (but it works for me!)

reply Ethan <gooberman gmail.com> writes:
This is another case of "Works for me!"

As a part of getting Binderoo working, I've long long long wanted 
to automagically create typedefs from alias declarations. But 
working out if something is an alias is difficult. For example:

struct SomeObject
{
     int foo;
}
alias NotSomeObject = SomeObject;
pragma( msg, NotSomeObject.stringof );
pragma( msg, __traits( identifier, NotSomeObject ) );

Will give you the following output:

SomeObject
SomeObject

This gets tricky when doing a __traits( allMembers ) loop. Alias 
declarations basically mean I end up parsing the same object 
twice. And, as you can see, there's no way to get the name of the 
alias.

Something has been staring me in the face for a very very very 
long time though. And I only just realised it when I was printing 
some debug information out in some Binderoo code. Add the 
following code to the above:

struct SomeWrapper( T )
{
     alias Type = T;
}
pragma( msg, SomeWrapper!SomeObject.Type.stringof );
static foreach( Symbol; __traits( allMembers, 
SomeWrapper!SomeObject ) )
{
     pragma( msg, Symbol );
}

And you get the following additional output:

SomeObject
Type
val

Of course! If the name obtained from allMembers doesn't match the 
stringof/identifier (depending on if it's a basic type or not) 
then you can rightly assume that you have an alias. Which means 
the following template can be used:

template IsAlias( alias Parent, string SymbolName )
{
     static bool impl()
     {
         foreach( MemberName; __traits( allMembers, Parent ) )
         {
             if( MemberName == SymbolName )
             {
                 mixin( "alias ThisSymbol = Alias!( " ~ 
fullyQualifiedName!Parent ~ "." ~ SymbolName ~ " );" );
                 return SymbolName != ThisSymbol.stringof;
             }
         }
         return false;
     }
     enum IsAlias = impl();
}

It'll need some more playing with to make it handle anything you 
throw at it. And while a template IsAlias( string 
FullyQualifedSymbolName ) would be easy to whip up, it would also 
be easy to misuse and not understand why. So I'm not going to do 
that.

But I finally have it. I can detect alias declarations, and since 
I have the originating symbol name I can thus export typedefs 
correctly.

I don't know if anyone else has done anything similar, and trying 
to search the documentation for std.traits and std.meta hasn't 
matched the terms I've looked for. But this feels like quite the 
moral victory for me since I've been trying to crack this problem 
for a very long time.
May 22 2018
parent Ethan <gooberman gmail.com> writes:
On Tuesday, 22 May 2018 at 20:34:34 UTC, Ethan wrote:
         foreach( MemberName; __traits( allMembers, Parent ) )
         {
             if( MemberName == SymbolName )
             {
                 mixin( "alias ThisSymbol = Alias!( " ~ 
 fullyQualifiedName!Parent ~ "." ~ SymbolName ~ " );" );
                 return SymbolName != ThisSymbol.stringof;
             }
         }
Looking over it, I questioned why I was doing this loop. It should work just the same without the loop, although as far as error checking goes you'd want to do a __traits( compiles ) test on that alias mixin before going ahead and performing that code.
May 22 2018