Yes this will

I think I may not have explained myself correctly, which is a mistake I often make in an effort to simplify the question =/

but, the assertion in the code below fails:

immutable class ModInfo {}

static moduleInfo(alias MODULE)() {
        return new ModInfo();
}

static getModuleInfo(alias mod)() {
        static if(__traits(hasMember, mod, "__module_info")) {
                return __traits(getMember, mod, "__module_info");
        } else {
                return moduleInfo!mod;
        }
}

void main() {
        immutable info = getModuleInfo!(main);
        immutable info2 = getModuleInfo!(main);
        assert(info == info2); // fail
}


The 'unique ModInfo per module' is done by the templated variable 1.

I didn't eventually use a variable template, but this did prompt me to give the templates/mixins section another read ;)

My design had several requirements which were very not easy to satisfy all at once, but I think I have finally found something that works.

I needed the module info to be generated once at compile time. Also, it needed to be available both at compile time, and runtime, which means I had to be able to reference it directly in both cases. But, at the same time, the caller had to have the option of placing the reflection implementation inside the actual module itself so that it could access to all the module's private symbols. So after 2 full days chasing errors and circular dependancies, the following seems to work:


// contains all reflection template subclasses used at compile time
mixin template _implementations(alias MODULE) {
        class ModuleDeclImpl(alias T) : ModuleDecl {
        static this() {
                        _allModules[ T.stringof[7..$] ] = getModuleInfo!T;
        }
    }
    // ...
}

// create reflection info
template moduleInfo(alias MODULE) {
        mixin _implementations!(MODULE);
        const(ModuleDecl) moduleInfo = new ModuleDeclImpl!MODULE;
}

// generate reflection for a module inside itself
mixin template reflection() {
        alias moduleAlias!(.stringof[7..$]) thisModule;
        static const(ModuleDecl) __module_info = moduleInfo!thisModule;
}

// generate reflection for a module from inside a different module
mixin template reflection(alias MODULE) {
        static assert(!__traits(hasMember, MODULE, "__module_info"),
"Reflection information already exists for " ~ MODULE.stringof);

mixin("static const(ModuleDecl) __" ~ MODULE.stringof[7..$] ~ "_info = moduleInfo!MODULE;");
}

// get reflection info at compile time
const(ModuleDecl) getModuleInfo(alias MODULE)() {
        static if(__traits(hasMember, MODULE, "__module_info")) {
                return __traits(getMember, MODULE, "__module_info");
        } else {
                static const(ModuleDecl) __module_info = moduleInfo!MODULE;
                return __module_info;
        }
}

// get reflection info at runtime
extern(C) export const(ModuleDecl) getModuleInfo(string name) {
        return ModuleDecl.allModules[name];
}

void main() {
        static m = getModuleInfo!(test);
        static m2 = getModuleInfo!(test);
        static m3 = getModuleInfo!(test);

        assert(m == m2); // PASS
        assert(m == m3); // PASS
}

Reply via email to