Thread overview
Error: Declaration is not yet implemented in CTFE
Nov 28, 2014
bitwise
Nov 28, 2014
Daniel Kozak
Nov 28, 2014
bitwise
Nov 28, 2014
Daniel Kozak
Nov 29, 2014
bitwise
Nov 29, 2014
bitwise
Nov 28, 2014
Daniel Murphy
November 28, 2014
The docs for template mixins do show mixins inside functions, so is this a bug, or is there something else I'm doing wrong?

//**************************
module main;
import std.traits;

class ModInfo {

}

mixin template moduleInfo(alias MODULE) {
	static const(ModInfo) __module_info = new ModInfo;
}

const(ModInfo) getModuleInfo(alias mod)() {
	static if(__traits(hasMember, mod, "__module_info")) {
		return __traits(getMember, mod, "__module_info");
	} else {
		mixin moduleInfo!mod;      // ERROR [1]
		return __module_info;
	}
}

void main() {
	static const(ModInfo) info = getModuleInfo!(main);
}
//**************************

[1] main.d(17,3): Error: Declaration mixin moduleInfo!(main);
 is not yet implemented in CTFE
main.d(23,31):        called from here: getModuleInfo()
November 28, 2014
Dne Fri, 28 Nov 2014 20:01:41 +0100 bitwise via Digitalmars-d <digitalmars-d@puremagic.com> napsal(a):

> The docs for template mixins do show mixins inside functions, so is this a bug, or is there something else I'm doing wrong?
>
> //**************************
> module main;
> import std.traits;
>
> class ModInfo {
>
> }
>
> mixin template moduleInfo(alias MODULE) {
> 	static const(ModInfo) __module_info = new ModInfo;
> }
>
> const(ModInfo) getModuleInfo(alias mod)() {
> 	static if(__traits(hasMember, mod, "__module_info")) {
> 		return __traits(getMember, mod, "__module_info");
> 	} else {
> 		mixin moduleInfo!mod;      // ERROR [1]
> 		return __module_info;
> 	}
> }
>
> void main() {
> 	static const(ModInfo) info = getModuleInfo!(main);
> }
> //**************************
>
> [1] main.d(17,3): Error: Declaration mixin moduleInfo!(main);
>   is not yet implemented in CTFE
> main.d(23,31):        called from here: getModuleInfo()


module main;

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);
}
November 28, 2014
On Friday, 28 November 2014 at 19:24:33 UTC, Daniel Kozak via Digitalmars-d wrote:
> Dne Fri, 28 Nov 2014 20:01:41 +0100 bitwise via Digitalmars-d <digitalmars-d@puremagic.com> napsal(a):
>
>> The docs for template mixins do show mixins inside functions, so is this a bug, or is there something else I'm doing wrong?
>>
>> //**************************
>> module main;
>> import std.traits;
>>
>> class ModInfo {
>>
>> }
>>
>> mixin template moduleInfo(alias MODULE) {
>> 	static const(ModInfo) __module_info = new ModInfo;
>> }
>>
>> const(ModInfo) getModuleInfo(alias mod)() {
>> 	static if(__traits(hasMember, mod, "__module_info")) {
>> 		return __traits(getMember, mod, "__module_info");
>> 	} else {
>> 		mixin moduleInfo!mod;      // ERROR [1]
>> 		return __module_info;
>> 	}
>> }
>>
>> void main() {
>> 	static const(ModInfo) info = getModuleInfo!(main);
>> }
>> //**************************
>>
>> [1] main.d(17,3): Error: Declaration mixin moduleInfo!(main);
>>  is not yet implemented in CTFE
>> main.d(23,31):        called from here: getModuleInfo()
>
>
> module main;
>
> 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);
> }

Thanks, but this still doesn't fix my problem. The idea is that getModuleInfo should return the same static copy of ModInfo at each call to avoid duplication. ModInfo is a recursive reflection of an entire module, so it could be huge.

My goal is that someone could create a global (ModInfo __module_info) object inside their own module through a mixin template, which would allow reflection of private members in that module. If getModuleInfo() was called for a module that was missing __ module_info, a static copy would be created inside getModuleInfo(). This would be the case if someone wanted to reflect a static library that they themselves did not compile.

November 28, 2014
"bitwise"  wrote in message news:bzzwikiplqydlzmphllp@forum.dlang.org...

> The docs for template mixins do show mixins inside functions, so is this a bug, or is there something else I'm doing wrong?

Both a bug, and you're doing something wrong.  CTFE should be giving you a 'cannot read static variable at compile time' error.

Try this:

import std.traits;

class ModInfo {

}

const(ModInfo) moduleInfo(alias MODULE) = new ModInfo(); // 1

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

void main() {
static const(ModInfo) info = getModuleInfo!(main);
}

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

November 28, 2014
Dne Fri, 28 Nov 2014 22:55:27 +0100 bitwise via Digitalmars-d <digitalmars-d@puremagic.com> napsal(a):

> On Friday, 28 November 2014 at 19:24:33 UTC, Daniel Kozak via Digitalmars-d wrote:
>> Dne Fri, 28 Nov 2014 20:01:41 +0100 bitwise via Digitalmars-d <digitalmars-d@puremagic.com> napsal(a):
>>
>>> The docs for template mixins do show mixins inside functions, so is this a bug, or is there something else I'm doing wrong?
>>>
>>> //**************************
>>> module main;
>>> import std.traits;
>>>
>>> class ModInfo {
>>>
>>> }
>>>
>>> mixin template moduleInfo(alias MODULE) {
>>> 	static const(ModInfo) __module_info = new ModInfo;
>>> }
>>>
>>> const(ModInfo) getModuleInfo(alias mod)() {
>>> 	static if(__traits(hasMember, mod, "__module_info")) {
>>> 		return __traits(getMember, mod, "__module_info");
>>> 	} else {
>>> 		mixin moduleInfo!mod;      // ERROR [1]
>>> 		return __module_info;
>>> 	}
>>> }
>>>
>>> void main() {
>>> 	static const(ModInfo) info = getModuleInfo!(main);
>>> }
>>> //**************************
>>>
>>> [1] main.d(17,3): Error: Declaration mixin moduleInfo!(main);
>>>  is not yet implemented in CTFE
>>> main.d(23,31):        called from here: getModuleInfo()
>>
>>
>> module main;
>>
>> 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);
>> }
>
> Thanks, but this still doesn't fix my problem. The idea is that getModuleInfo should return the same static copy of ModInfo at each call to avoid duplication. ModInfo is a recursive reflection of an entire module, so it could be huge.
>

Yes this will
November 29, 2014
>> 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
}

November 29, 2014
> void main() {
> 	static m = getModuleInfo!(test);
> 	static m2 = getModuleInfo!(test);
> 	static m3 = getModuleInfo!(test);
>
> 	assert(m == m2); // PASS
> 	assert(m == m3); // PASS
> }

correction:

static m = getModuleInfo!(test);
static m2 = getModuleInfo!(test);
auto m3 = getModuleInfo("test");   // runtime retrieval

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