www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to correctly generate enums at compile time.

reply Kevin Balbas <kbalbas gmail.com> writes:
I've got the following code snippet, which almost does what I 
want.

struct TaggedType {}

 TaggedType
struct Foo {}

 TaggedType
struct Bar {}

string GenerateTypeEnum()
{
     string enumString = "enum TypeEnum {";
     foreach (name; __traits(allMembers, mixin(__MODULE__)))
     {
         import std.traits;
         static if (hasUDA!(mixin(name), TaggedType))
         {
             enumString ~= name;
             enumString ~= "Type,";
         }
     }
     enumString ~= "}";
     return enumString;
}

// generates enum TypeEnum {FooType,BarType,}
mixin(GenerateTypeEnum());

This works great, except that TypeEnum isn't accessible from 
other modules (undefined identifier 'TypeEnum'), which is kind of 
the point of doing this (I'm using the enum as a system-wide tag 
for inter-thread communication).  I can imagine why this would be 
the case, but it's a pretty serious problem.  Is there a way to 
do this?
Apr 30 2017
parent reply jkpl <jkpl nowhere.de> writes:
On Sunday, 30 April 2017 at 20:05:59 UTC, Kevin Balbas wrote:
 I've got the following code snippet, which almost does what I 
 want.

 struct TaggedType {}

  TaggedType
 struct Foo {}

  TaggedType
 struct Bar {}

 string GenerateTypeEnum()
 {
     string enumString = "enum TypeEnum {";
     foreach (name; __traits(allMembers, mixin(__MODULE__)))
     {
         import std.traits;
         static if (hasUDA!(mixin(name), TaggedType))
         {
             enumString ~= name;
             enumString ~= "Type,";
         }
     }
     enumString ~= "}";
     return enumString;
 }

 // generates enum TypeEnum {FooType,BarType,}
 mixin(GenerateTypeEnum());

 This works great, except that TypeEnum isn't accessible from 
 other modules (undefined identifier 'TypeEnum'), which is kind 
 of the point of doing this (I'm using the enum as a system-wide 
 tag for inter-thread communication).  I can imagine why this 
 would be the case, but it's a pretty serious problem.  Is there 
 a way to do this?
if i put your sniped in b.d and import in a.d b then i'm able to access TypeEnum. You r problem must be something stupid that's not related to UDA/mixins. That leads to this question (sorry) but at least do you import the module that contains TypeEnum ?
Apr 30 2017
parent reply Kevin Balbas <kbalbas gmail.com> writes:
On Sunday, 30 April 2017 at 20:58:36 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 20:05:59 UTC, Kevin Balbas wrote:
 I've got the following code snippet, which almost does what I 
 want.

 struct TaggedType {}

  TaggedType
 struct Foo {}

  TaggedType
 struct Bar {}

 string GenerateTypeEnum()
 {
     string enumString = "enum TypeEnum {";
     foreach (name; __traits(allMembers, mixin(__MODULE__)))
     {
         import std.traits;
         static if (hasUDA!(mixin(name), TaggedType))
         {
             enumString ~= name;
             enumString ~= "Type,";
         }
     }
     enumString ~= "}";
     return enumString;
 }

 // generates enum TypeEnum {FooType,BarType,}
 mixin(GenerateTypeEnum());

 This works great, except that TypeEnum isn't accessible from 
 other modules (undefined identifier 'TypeEnum'), which is kind 
 of the point of doing this (I'm using the enum as a 
 system-wide tag for inter-thread communication).  I can 
 imagine why this would be the case, but it's a pretty serious 
 problem.  Is there a way to do this?
if i put your sniped in b.d and import in a.d b then i'm able to access TypeEnum. You r problem must be something stupid that's not related to UDA/mixins. That leads to this question (sorry) but at least do you import the module that contains TypeEnum ?
Yes, and in fact, if I manually comment out the code (in my actual program, not the test program) in the same module and replace it with a hard-coded enum, the other code can access it perfectly. I wouldn't be surprised if it was something stupid, but I'm not even sure what could go wrong between those two cases. I figured it was some kind of ordering thing, but I honestly have no idea. Strangely enough, it does work fine in the test snippet, so I'm trying to figure out what could be going on since I literally copied the function verbatim from my test program to my main one. Now that I've realized this I'm working on how to repro it in the smaller program.
Apr 30 2017
parent reply jkpl <jkpl nowhere.de> writes:
On Sunday, 30 April 2017 at 21:13:07 UTC, Kevin Balbas wrote:
 On Sunday, 30 April 2017 at 20:58:36 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 20:05:59 UTC, Kevin Balbas wrote:
Strangely enough, it does work fine in the test snippet,
As well if you import the snippet in another module. That's what i tried to tell. try to reduce step by step; The problem cant be the stuff you mix.
Apr 30 2017
parent reply Kevin Balbas <kbalbas gmail.com> writes:
On Sunday, 30 April 2017 at 21:31:22 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 21:13:07 UTC, Kevin Balbas wrote:
 On Sunday, 30 April 2017 at 20:58:36 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 20:05:59 UTC, Kevin Balbas wrote:
Strangely enough, it does work fine in the test snippet,
As well if you import the snippet in another module. That's what i tried to tell. try to reduce step by step; The problem cant be the stuff you mix.
I was able to fix the error by simplifying and slashing down my actual code to a few hundred lines and 4 modules (3 plus a stub main), and even then the error only goes away if I compile the modules in a very specific order with dmd. Namely, both the main() file and the file containing the enum have to be compiled after all of the things that use the enum, and one of the two dependents has to be compiled before the other. I have no idea *why* that's the case, but it seems to be. My actual project uses dub/visuald for building, so I don't really tinker with file ordering. Is this a thing that's supposed to happen?
Apr 30 2017
parent jkpl <jkpl nowhere.de> writes:
On Sunday, 30 April 2017 at 22:03:02 UTC, Kevin Balbas wrote:
 On Sunday, 30 April 2017 at 21:31:22 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 21:13:07 UTC, Kevin Balbas wrote:
 On Sunday, 30 April 2017 at 20:58:36 UTC, jkpl wrote:
 On Sunday, 30 April 2017 at 20:05:59 UTC, Kevin Balbas wrote:
Strangely enough, it does work fine in the test snippet,
[...] My actual project uses dub/visuald for building, so I don't really tinker with file ordering. Is this a thing that's supposed to happen?
Hell no !
Apr 30 2017