February 15, 2005
> The problem with having the compiler insert implicit static ctors in
> modules
> that don't have them is that it will impose a likely unresolvable order of
> construction problem. In other words, it would become impossible to have
> circular imports (which is possible now if at least one of the modules in
> the circle doesn't have a static ctor).

Circular imports are only a problem if the static initializers have circular
dependencies. One way out is to make this more explicit by putting the
dependencies on the static ctors somehow. In other words instead of saying
"this module depends on modules foo and bar" have "this static ctor depends
on modules foo and bar". That could take the pressure off of circular
modules and put it closer to the real problem of circular static ctors
(which should be illegal), and that way modules without an explicit static
ctor can implicitly recurse over their imported modules.
More concretely, line 120 in std.moduleinit.d
  _moduleCtor2(m.importedModules, 0);
should recurse only over those imported modules that are actually needed by
the static ctor in the current module m.
I don't have a good syntax for expressing the static ctor dependencies,
though. I guess by default a static ctor would have all of the module
imports as dependencies.


February 15, 2005
On Mon, 14 Feb 2005 21:51:45 -0500, Ben Hinkle <ben.hinkle@gmail.com> wrote:

>> The problem with having the compiler insert implicit static ctors in
>> modules
>> that don't have them is that it will impose a likely unresolvable order of
>> construction problem. In other words, it would become impossible to have
>> circular imports (which is possible now if at least one of the modules in
>> the circle doesn't have a static ctor).
>
> Circular imports are only a problem if the static initializers have circular
> dependencies. One way out is to make this more explicit by putting the
> dependencies on the static ctors somehow. In other words instead of saying
> "this module depends on modules foo and bar" have "this static ctor depends
> on modules foo and bar". That could take the pressure off of circular
> modules and put it closer to the real problem of circular static ctors
> (which should be illegal), and that way modules without an explicit static
> ctor can implicitly recurse over their imported modules.
> More concretely, line 120 in std.moduleinit.d
>   _moduleCtor2(m.importedModules, 0);
> should recurse only over those imported modules that are actually needed by
> the static ctor in the current module m.
> I don't have a good syntax for expressing the static ctor dependencies,
> though. I guess by default a static ctor would have all of the module
> imports as dependencies.

Ideally this would only be required if a circular import was identified.

Identifying circular imports is difficult isn't it? It could be a circle of arbitrary length. I guess the compiler can just barf if it gets too 'deep' and hopefully give the programmer a good indication of where to use this syntax to avoid the circle.

Regan
February 15, 2005
"Kris" <Kris_member@pathlink.com> wrote in message news:curk2i$2b91$1@digitaldaemon.com...
> In article <curj1o$2afu$1@digitaldaemon.com>, Walter says...
> >The problem with having the compiler insert implicit static ctors in
modules
> >that don't have them is that it will impose a likely unresolvable order
of
> >construction problem. In other words, it would become impossible to have circular imports (which is possible now if at least one of the modules in the circle doesn't have a static ctor).
>
> Thanks for the reply;
>
> As I understand it, such a case is detected by the runtime initialization.
At
> this time, it throws an exception ~ could it be changed to simply
terminate the
> tail-chasing instead?

If A and B mutually import each other, that leaves us with the order of A and B being initialized as unspecified, although they may or may not depend on each other. It may work on one platform, yet fail on another in a way that one can't predict. So I think it is better to throw the exception, forcing the programmer to organize it in such a way that it is not circular.

> >Putting a static this(){} in B will resolve the problem. It isn't
perfect,
> >but it works.
> Right. The true problem with this is education ~ the issue is not even documented. If it were, then you could hardly expect just anyone to say
"oh well
> .. of course that's the case". It's not a good place for D to be so,
better to
> find a compiler-based resolution ~ if indeed there is one

The documentation can always be improved. To be honest, I hadn't thought of the proxy situation you're experiencing. I too prefer to solve it within the language rather than as a documented wart. I'll think about it and see what I can do.


February 15, 2005
"Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:curo45$2eea$1@digitaldaemon.com...
> Circular imports are only a problem if the static initializers have
circular
> dependencies. One way out is to make this more explicit by putting the dependencies on the static ctors somehow.

While this would work, I think in real life it would be very brittle and result in many bugs. The trouble is when maintenance programmers change the code, will they change the dependency list, and if they do, will they get it right? This is like the syntax in gcc for telling the compiler which registers are used by the inline assembly, except it's even harder for the programmer to get right.

Essentially, any language feature where the programmer has to express something twice is a bug. C header files are one such <g>.


February 15, 2005
In article <curr90$2h5h$1@digitaldaemon.com>, Walter says...
>
>
>"Kris" <Kris_member@pathlink.com> wrote in message news:curk2i$2b91$1@digitaldaemon.com...
>> In article <curj1o$2afu$1@digitaldaemon.com>, Walter says...
>> >The problem with having the compiler insert implicit static ctors in
>modules
>> >that don't have them is that it will impose a likely unresolvable order
>of
>> >construction problem. In other words, it would become impossible to have circular imports (which is possible now if at least one of the modules in the circle doesn't have a static ctor).
>>
>> Thanks for the reply;
>>
>> As I understand it, such a case is detected by the runtime initialization.
>At
>> this time, it throws an exception ~ could it be changed to simply
>terminate the
>> tail-chasing instead?
>
>If A and B mutually import each other, that leaves us with the order of A and B being initialized as unspecified, although they may or may not depend on each other. It may work on one platform, yet fail on another in a way that one can't predict. So I think it is better to throw the exception, forcing the programmer to organize it in such a way that it is not circular.

Sure; that certainly makes sense. To catch that at compile-time would be rather difficult, since you don't know all the link-units.

>
>> >Putting a static this(){} in B will resolve the problem. It isn't
>perfect,
>> >but it works.
>> Right. The true problem with this is education ~ the issue is not even documented. If it were, then you could hardly expect just anyone to say
>"oh well
>> .. of course that's the case". It's not a good place for D to be so,
>better to
>> find a compiler-based resolution ~ if indeed there is one
>
>The documentation can always be improved. To be honest, I hadn't thought of the proxy situation you're experiencing. I too prefer to solve it within the language rather than as a documented wart. I'll think about it and see what I can do.


Excellent!

May I suggest something?

To recap: right now the proxy is excluded by default, which can cause a problem. Currently, the resolution is to manually add a dummy static ctor to the proxy.

Assume (for the moment) the proxy were to be included by default. Further suppose this then causes a circular-reference exception to be thrown. At that point, you really *do* have a true circular reference (by proxy) which the programmer should be 'encouraged' to break. I mean, manually adding a ctor in such a case would throw the exception too ... right? Excluding the proxy (by default) would actually *mask* that circularity instead.


Alternatively:

If the concerns were reversed, would the situation be notably more appealing? I mean, if the proxy were included by default, and there were some means of excluding it (perhaps via a pragma)? That seems kinda gnarly though ...

Just thoughts;

- Kris


February 15, 2005
On Mon, 14 Feb 2005 19:59:06 -0800, Walter wrote:

> 
> "Ben Hinkle" <ben.hinkle@gmail.com> wrote in message news:curo45$2eea$1@digitaldaemon.com...
>> Circular imports are only a problem if the static initializers have
> circular
>> dependencies. One way out is to make this more explicit by putting the dependencies on the static ctors somehow.
> 
> While this would work, I think in real life it would be very brittle and result in many bugs. The trouble is when maintenance programmers change the code, will they change the dependency list, and if they do, will they get it right? This is like the syntax in gcc for telling the compiler which registers are used by the inline assembly, except it's even harder for the programmer to get right.

Interesting that you note that.  I ran into trouble with an inline
assembler conflict in a C library I was compiling for use with D.  The
linux project was originally designed to compile to a static
lib only.  I wanted a shared lib version, so I changed some parameters in
the makefile and compiled away only to find that adding -PIC (a necessary
compile flag for shared library creation) caused the build to fail at an
inline assembler section in one of the source files.  Apparently the
assembler accessed EAX which is important for use when compiling for
position independent code (PIC).  The compiler died with an error
describing the illegal access for this case.  The author obviously had not
considered this possibility. Thankfully, the inline section wasn't a
critical requirement and could be disabled.

> Essentially, any language feature where the programmer has to express something twice is a bug. C header files are one such <g>.

Well, I'd say that D import modules amount to the same thing in instances of closed source libraries that provided stripped modules for public use. I don't think the world is completely opensource yet. :-)


February 15, 2005
"John Reimer" <brk_6502@yahoo.com> wrote in message news:pan.2005.02.15.04.27.18.367664@yahoo.com...
> > Essentially, any language feature where the programmer has to express something twice is a bug. C header files are one such <g>.
>
> Well, I'd say that D import modules amount to the same thing in instances of closed source libraries that provided stripped modules for public use. I don't think the world is completely opensource yet. :-)

That isn't a problem with the language, it's more a weakness of the current implementation. There's no reason why, when compiling a module, the compiler cannot emit a "symbol" file. Then, when another module imports it, the "symbol" file is read instead. The "symbol" file will only have in it what is necessary for importation.

That was the original design for DMD, but to get the compiler done and working I took the expedient route of just reparsing the import source file instead.


February 15, 2005
Walter wrote:
> "John Reimer" <brk_6502@yahoo.com> wrote in message
> news:pan.2005.02.15.04.27.18.367664@yahoo.com...
> 
>>>Essentially, any language feature where the programmer has to express
>>>something twice is a bug. C header files are one such <g>.
>>
>>Well, I'd say that D import modules amount to the same thing in instances
>>of closed source libraries that provided stripped modules for public
>>use. I don't think the world is completely opensource yet. :-)
> 
> 
> That isn't a problem with the language, it's more a weakness of the current
> implementation. There's no reason why, when compiling a module, the compiler
> cannot emit a "symbol" file. Then, when another module imports it, the
> "symbol" file is read instead. The "symbol" file will only have in it what
> is necessary for importation.

Excellent! Pre-compiled "headers" :-)

If the compiler becomes any faster, it might just cause a rupture in the fabric of space/time ...
February 15, 2005
"kris" <fu@bar.org> wrote in message news:cus9ou$2u39$2@digitaldaemon.com...
> Excellent! Pre-compiled "headers" :-)

Precompiled headers are a kludge to try and get module performance into C/C++. The C++ "export" is a sorry attempt to run include and module semantics through a mixmaster.

> If the compiler becomes any faster, it might just cause a rupture in the fabric of space/time ...

It being faster would be a nice side effect, but the primary purpose would be to avoid needing to sometimes create two versions of the module source.


February 15, 2005
"Kris" <Kris_member@pathlink.com> wrote in message news:curtjf$2j35$1@digitaldaemon.com...
> Excellent!
>
> May I suggest something?

Too late! I already figured out a way to fix it. It's 2 lines of code added to dmd <g>.