digitalmars.D - Could static ctors / module init be a little more intelligent?
- Jarrett Billingsley (40/40) Jul 14 2005 Say I have two modules named A and B.
- Ben Hinkle (7/20) Jul 14 2005 [snip]
- Jarrett Billingsley (12/19) Jul 14 2005 But that's what I said - the check to see if the other module is initial...
- Ben Hinkle (16/36) Jul 14 2005 Maybe I don't understand. What I meant was:
- Jarrett Billingsley (7/20) Jul 14 2005 I didn't think about having code like you posted. Now this fits right i...
- Ben Hinkle (7/29) Jul 14 2005 Don't be sorry! I remember fairly recent long threads about exactly what...
- Walter (8/13) Jul 14 2005 you
- Uwe Salomon (19/23) Jul 14 2005 Yes, that's it. We should really avoid cluttering the language with
Say I have two modules named A and B. Each module needs to know of a class from the other module. Each module also needs a static ctor. Neither static ctor refers to the other module, only to stuff in the current module. However, when run, I get the error "Error: circular initialization dependency with module A." This is the result of some rather simplistic dependence determination on the part of the compiler. Both have static ctors, and both import each other, therefore, it _must_ be a circular dependency. But look at this: [A.d] module a; private import b; int x; static this() { x=5; } void fork() { x=y; } [B.d] module b; private import b; int y; static this() { y=10; } void knife() { y=x; } As you can see, neither module requires for the other module to be initialized when it is. But I get the error at runtime, nonetheless. This is irritating. Could the check for "depended-upon module initialization" be done when a member is accessed in the static ctor() rather than unconditionally?
Jul 14 2005
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:db6867$4oa$1 digitaldaemon.com...Say I have two modules named A and B. Each module needs to know of a class from the other module. Each module also needs a static ctor. Neither static ctor refers to the other module, only to stuff in the current module. However, when run, I get the error "Error: circular initialization dependency with module A." This is the result of some rather simplistic dependence determination on the part of the compiler. Both have static ctors, and both import each other, therefore, it _must_ be a circular dependency.[snip]This is irritating. Could the check for "depended-upon module initialization" be done when a member is accessed in the static ctor() rather than unconditionally?What about when the static ctor calls something that accesses the other module? I think the current rule is the most reasonable since trying to figure out the run-time dependencies is impossible in general.
Jul 14 2005
"Ben Hinkle" <bhinkle mathworks.com> wrote in message news:db6k70$fd1$1 digitaldaemon.com...But that's what I said - the check to see if the other module is initialized should be done before a member of it is accessed in the module ctor, instead of before the module ctor is run.This is irritating. Could the check for "depended-upon module initialization" be done when a member is accessed in the static ctor() rather than unconditionally?What about when the static ctor calls something that accesses the other module?I think the current rule is the most reasonable since trying to figure out the run-time dependencies is impossible in general.That's not entirely true. At least for the static ctors, it would be possible to see if any members of an imported module are used. In the semantic pass, see if anything resolves to a symbol declared in the imported module - if so, that module depends upon the imported module to be initialized before. This way, the compiler would be able to determine the dependence graphs, and true circular dependencies could be reported at compile-time.
Jul 14 2005
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:db6m5e$gi6$1 digitaldaemon.com..."Ben Hinkle" <bhinkle mathworks.com> wrote in message news:db6k70$fd1$1 digitaldaemon.com...Maybe I don't understand. What I meant was: module a; import b; static this() { foo(); } void foo(){bar();} module b; import a; statis this(){bar();} void bar(){printf("who wins?\n");} In order for dmd to know that a's ctor depends on b but b's ctor doesn't it has to track the run-time behavior. Imagine now that the logic before calling bar is arbitrarily complex. Imagine if foo was void foo(){ if (hell is frozen) bar(); }But that's what I said - the check to see if the other module is initialized should be done before a member of it is accessed in the module ctor, instead of before the module ctor is run.This is irritating. Could the check for "depended-upon module initialization" be done when a member is accessed in the static ctor() rather than unconditionally?What about when the static ctor calls something that accesses the other module?It just seems like a slippeery slope to me.I think the current rule is the most reasonable since trying to figure out the run-time dependencies is impossible in general.That's not entirely true. At least for the static ctors, it would be possible to see if any members of an imported module are used. In the semantic pass, see if anything resolves to a symbol declared in the imported module - if so, that module depends upon the imported module to be initialized before. This way, the compiler would be able to determine the dependence graphs, and true circular dependencies could be reported at compile-time.
Jul 14 2005
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:db6q3a$jfk$1 digitaldaemon.com...Maybe I don't understand. What I meant was: module a; import b; static this() { foo(); } void foo(){bar();} module b; import a; statis this(){bar();} void bar(){printf("who wins?\n");} In order for dmd to know that a's ctor depends on b but b's ctor doesn't it has to track the run-time behavior. Imagine now that the logic before calling bar is arbitrarily complex. Imagine if foo was void foo(){ if (hell is frozen) bar(); }I didn't think about having code like you posted. Now this fits right in with determining whether to issue an error for "function does not return a value" or not. I'm sorry for cluttering up the board with so many half-thought-out suggestions..
Jul 14 2005
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message news:db6um6$mn0$1 digitaldaemon.com..."Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:db6q3a$jfk$1 digitaldaemon.com...Don't be sorry! I remember fairly recent long threads about exactly what you are talking about: circular module dependencies and the semantics of module ctors. I think it will come up again, too. Over time I wouldn't be surprised if there evolves a way to tell the compiler that a's ctor depends on b but b's doesn't depend on a. What that syntax would look like is anyone guess.Maybe I don't understand. What I meant was: module a; import b; static this() { foo(); } void foo(){bar();} module b; import a; statis this(){bar();} void bar(){printf("who wins?\n");} In order for dmd to know that a's ctor depends on b but b's ctor doesn't it has to track the run-time behavior. Imagine now that the logic before calling bar is arbitrarily complex. Imagine if foo was void foo(){ if (hell is frozen) bar(); }I didn't think about having code like you posted. Now this fits right in with determining whether to issue an error for "function does not return a value" or not. I'm sorry for cluttering up the board with so many half-thought-out suggestions..
Jul 14 2005
"Ben Hinkle" <ben.hinkle gmail.com> wrote in message news:db70l8$o5d$1 digitaldaemon.com...Don't be sorry! I remember fairly recent long threads about exactly whatyouare talking about: circular module dependencies and the semantics ofmodulectors. I think it will come up again, too. Over time I wouldn't besurprisedif there evolves a way to tell the compiler that a's ctor depends on b but b's doesn't depend on a. What that syntax would look like is anyone guess.Sometimes I think a simple rule that is easilly explained and understood is better than a complex rule with many border cases, even if the latter does handle a few more cases.
Jul 14 2005
Sometimes I think a simple rule that is easilly explained and understood is better than a complex rule with many border cases, even if the latter does handle a few more cases.Yes, that's it. We should really avoid cluttering the language with "small, simple" fixes to support every feature one could possibly imagine. Most of the time, module initializers are not needed anyways (as with constructors), and for the other cases one could either redesign the module dependencies, or simply initialize the second module from the first: module initialize.me; private import initialize.myself; package MyStruc* myStruc; module initialize.myself; private import initialize.me; package MyStruc* myOtherStruc; static this() { myOtherStruc = new MyStruc; initialize.me.myStruc = new MyStruc; } Or something similar... Ciao uwe
Jul 14 2005