Fixing cyclic import static construction problems

Rainer Schuetze r.sagitario at gmx.de
Fri Nov 30 00:13:09 PST 2012



On 11/29/2012 5:51 PM, Max Samukha wrote:
> On Thursday, 29 November 2012 at 15:18:11 UTC, Paulo Pinto wrote:
>>
>> Maybe you care to provide an example?
>>
>
> The general problem is constructing global data structures based on data
> introspected at compile-time.
>
> My specific problem is extending scarce runtime type information
> provided by the language with something usable for runtime reflection.
> With lots of detail omitted:
>
> module reflect;
>
> Meta[string] metas;
> mixin template Reflect(alias object) {
>      static this()
>      {
>          auto m = meta!(object);
>          metas[m.fullName] ~= m;
>      }
> }
>
>
> module a;
> import reflect;
>
> struct S
> {
> }
> mixin Reflect!S;
>
> The meta-object for S is automatically made available at runtime through
> the global metas array. Note that we do not want to force the user to
> register the meta-object manually because then it would not be a "better
> architecture".
>
> The important (Andrei somehow thinks it is not) requirement is there
> must not be circular dependency issues for the users of the "reflect"
> module.
>

How about running your own set of "constructors" searching the module 
info array, searching for specific classes in the module that are added 
by a mixin:

----------------------------------
module register;

RegisterBase[string] registry;

void doRegister(string name, RegisterBase r) { registry[name] = r; }

class RegisterBase
{
	abstract void _register();
}

template Register(string name)
{
	enum string Register = "
	class Register : RegisterBase
	{
		override void _register() { doRegister(\"" ~ name ~ "\", this); }
	}
	";
}

void registerAll()
{
	foreach(m; ModuleInfo)
	{
		TypeInfo_Class[] clss = m.localClasses();
		foreach(c; clss)
		{
			if(c.base is RegisterBase.classinfo)
			{
				if(auto reg = cast(RegisterBase) c.create())
				{
					reg._register();
				}
			}
		}
	}
}


-----------------------
module a;
import register;

mixin(Register!"a");

-----------------------
module main;
import std.stdio;
import register;

void main()
{
	registerAll();
	foreach(a, o; registry)
		writeln(a, " ", o);
}

This might also work for the benchmark module.


More information about the Digitalmars-d mailing list