order of static constructor execution
Fawzi Mohamed
fawzi at gmx.ch
Fri Mar 12 03:06:25 PST 2010
On 12-mar-10, at 09:59, Don wrote:
> BCS wrote:
>> Hello Walter,
>>> 2. If a loop is detected, rather than issuing an error message,
>>> simply
>>> arbitrarily pick one order and continue constructing.
>> How about a way to explicitly cut edges in the graph (tagging
>> imports with "pragma(nodep)" or "@nodep" for instance)? That has
>> the same end effect but for only a little more work, removes any
>> non-determinism and allows for easy control of how things are
>> resolved.
>
> I agree. Seems to me that if a circular import exists, it's really
> something that the programmer needs to think about, and so it's
> reasonable for it to be explicit.
>
> A really harsh solution would be:
>
> pragma(nodependency, somepackage.somemodule);
>
> The compiler could check that somepackage.somemodule actually
> defines a static constructor. And it could even check that a
> circular import situation actually exists. This would force the
> pragma to be maintained correctly.
I think that the main problem comes from static initializers that are
mixed in and by themselves have no circular dependency. So annotations
have to be at the static initializer level, not at the module level.
One way to solve this would be to add
@dependOnly(module1,...) static this(){ }
then each module would have 2 dependencies:
* indirectDeps
imported modules + all dependOnly modules
* directDeps
look at all static initializers in the module:
- plain static this() -> add all imported modules as dependency
- annotated static this -> add all dependOnly dependencies
* allDeps
the list of module that have to be initialized before that module
and is build from the previous ones as:
direct deps + all indirect deps of those modules
more explicitly
allDeps(a){
deps=[]
foreach(m in a.directDeps){
if (m in deps) continue;
deps~=m;
addDeps2(m,deps);
}
return deps;
}
addDeps2(a, ref deps){
if (a in deps) return;
foreach(m in a.indirectDeps){
if (m in deps) continue;
deps~=m;
addDeps2(m,deps);
}
}
then you can sort the modules that have static initializers (and only
those) using:
compare(a,b){
if (a in b.allDeps){
if (b in a.allDeps){
error("non comparable, circular dep between ",a,b);
}
return 1;
}
if (b in a.allDeps){
return -1;
}
return 0;
}
this is more work, but would be perfectly defined.
conflicting ordering would still be disallowed, but circularly
dependent modules can have initializers if all their initializers
depend only on modules that are not circularly dependent.
Fawzi
More information about the Digitalmars-d
mailing list