www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DI File Generation

reply "Adam Wilson" <flyboynw gmail.com> writes:
Hello everyone,

As some of you may be aware I have been working on improvements to the .di  
file generation capabilities in D and I've run across a few things that I  
think should be put to the community.

The first involves the handling of variable instantiation. Say you create  
the following member variable in a class:

export int Foo = 1;

Currently the di generation output is identical to the above line. My  
understanding is that, similar to C/C++, D doesn't care if you keep the  
initializer in the include file so this is primarily a stylistic question.
Should we keep the output as is, or remove the initializer? My personal  
preference is to remove the initializer but I think the community should  
decide.

Another question that has come up pertains to the reason for the original  
implementation of DI generation, inlining. According to what I've read on  
these newsgroups and various other sources, DI generation is supposed to  
include the implementation for some small functions that would be good  
inlining candidates, however, it looks like is actually happening is that  
all DMD does is check to see if there are any cases where the compiler  
would fail if it attempted to inline the function. As long as the compiler  
can compile it, it gets thrown into the DI file, regardless of size. My  
current patches never include the implementation, and I think that for  
most people this is a reasonable solution, if not ideal. All of the people  
I've talked to seemed to agree. What do you think? Does this work for you?  
Should there be a way to specify the maximum size of an inline function?  
NOTE: Doing this would require at least a command line switch and probably  
some significant reworking of the function symbol exporter. As such it'd  
take a lot more time to get into to D; I'd recommend implementing the  
simple solution first then adding this only if it's requested by a  
significant number of people.

The next question is primarily directed at Walter, but anybody who knows  
anything about the compiler internals is welcome to chime in. For  
functions defined in Class and Interfaces, calling isFuncDeclaration() as  
I iterate through the symbol tree works as expected and returns the  
Function. However, when I try to call that on a function that is declared  
in a module (with no surrounding class) or in a struct, it always returns  
null, regardless of whether or not it's actually a function. Is there any  
way to determine if the symbol is a function when it's not a class member?  
NOTE: As near as I can tell, it is actually a FuncDeclaration.

The final bit of DI generation revolves around the handling of protected  
functions in exported classes. But that's better suited to a separate  
topic as that involves the general design of scoping in D2 and isn't  
limited to DI generation. I'll be posting another topic on that soon.

Thank you all for taking the time to read and chime in on this!

-- 
Adam Wilson
Project Coordinator
The Horizon Project
http://www.thehorizonproject.org/
Dec 14 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/14/2011 07:47 PM, Adam Wilson wrote:
 Hello everyone,

 As some of you may be aware I have been working on improvements to the
 .di file generation capabilities in D

Nice!
 and I've run across a few things
 that I think should be put to the community.

 The first involves the handling of variable instantiation. Say you
 create the following member variable in a class:

 export int Foo = 1;

 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep the
 initializer in the include file so this is primarily a stylistic question.
 Should we keep the output as is, or remove the initializer? My personal
 preference is to remove the initializer but I think the community should
 decide.

 Another question that has come up pertains to the reason for the
 original implementation of DI generation, inlining. According to what
 I've read on these newsgroups and various other sources, DI generation
 is supposed to include the implementation for some small functions that
 would be good inlining candidates, however, it looks like is actually
 happening is that all DMD does is check to see if there are any cases
 where the compiler would fail if it attempted to inline the function. As
 long as the compiler can compile it, it gets thrown into the DI file,
 regardless of size. My current patches never include the implementation,
 and I think that for most people this is a reasonable solution, if not
 ideal. All of the people I've talked to seemed to agree. What do you
 think? Does this work for you?

Yes, it is always possible to include the function bodies manually or to compile the modules together for release mode if inlining is that important. For now, .di generation should ideally just work.
 Should there be a way to specify the
 maximum size of an inline function? NOTE: Doing this would require at
 least a command line switch and probably some significant reworking of
 the function symbol exporter. As such it'd take a lot more time to get
 into to D; I'd recommend implementing the simple solution first then
 adding this only if it's requested by a significant number of people.

 The next question is primarily directed at Walter, but anybody who knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration()
 as I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is
 declared in a module (with no surrounding class) or in a struct, it
 always returns null, regardless of whether or not it's actually a
 function. Is there any way to determine if the symbol is a function when
 it's not a class member? NOTE: As near as I can tell, it is actually a
 FuncDeclaration.

 The final bit of DI generation revolves around the handling of protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.

 Thank you all for taking the time to read and chime in on this!

How will your patch handle top level string mixins/static if's/version declarations?
Dec 14 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/14/2011 09:05 PM, Adam Wilson wrote:
 On Wed, 14 Dec 2011 10:58:30 -0800, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 12/14/2011 07:47 PM, Adam Wilson wrote:
 Hello everyone,

 As some of you may be aware I have been working on improvements to the
 .di file generation capabilities in D

Nice!
 and I've run across a few things
 that I think should be put to the community.

 The first involves the handling of variable instantiation. Say you
 create the following member variable in a class:

 export int Foo = 1;

 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep the
 initializer in the include file so this is primarily a stylistic
 question.
 Should we keep the output as is, or remove the initializer? My personal
 preference is to remove the initializer but I think the community should
 decide.

 Another question that has come up pertains to the reason for the
 original implementation of DI generation, inlining. According to what
 I've read on these newsgroups and various other sources, DI generation
 is supposed to include the implementation for some small functions that
 would be good inlining candidates, however, it looks like is actually
 happening is that all DMD does is check to see if there are any cases
 where the compiler would fail if it attempted to inline the function. As
 long as the compiler can compile it, it gets thrown into the DI file,
 regardless of size. My current patches never include the implementation,
 and I think that for most people this is a reasonable solution, if not
 ideal. All of the people I've talked to seemed to agree. What do you
 think? Does this work for you?

Yes, it is always possible to include the function bodies manually or to compile the modules together for release mode if inlining is that important. For now, .di generation should ideally just work.
 Should there be a way to specify the
 maximum size of an inline function? NOTE: Doing this would require at
 least a command line switch and probably some significant reworking of
 the function symbol exporter. As such it'd take a lot more time to get
 into to D; I'd recommend implementing the simple solution first then
 adding this only if it's requested by a significant number of people.

 The next question is primarily directed at Walter, but anybody who knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration()
 as I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is
 declared in a module (with no surrounding class) or in a struct, it
 always returns null, regardless of whether or not it's actually a
 function. Is there any way to determine if the symbol is a function when
 it's not a class member? NOTE: As near as I can tell, it is actually a
 FuncDeclaration.

 The final bit of DI generation revolves around the handling of protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.

 Thank you all for taking the time to read and chime in on this!

How will your patch handle top level string mixins/static if's/version declarations?

At the moment, it doesn't do anything with them that I know off, but I don't know enough about how the compiler handles those constructs to give a good answer. Although if you have a piece of code that you can share for testing against my patches, i'll let you know.

I think currently it just creates a corrupted .di file if it encounters the construct. Ideally it would just expand them to make their compilation faster.
Dec 14 2011
prev sibling next sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
Thanks for the nice work.

Personally I would like that DI files would work like the
interfaces work in another module aware languages.

The interface is just that, the interface. Everything that
has to do with code or variable initialization is part of the
implementation part.

--
Paulo

Am 14.12.2011 19:47, schrieb Adam Wilson:
 Hello everyone,

 As some of you may be aware I have been working on improvements to the
 .di file generation capabilities in D and I've run across a few things
 that I think should be put to the community.

 The first involves the handling of variable instantiation. Say you
 create the following member variable in a class:

 export int Foo = 1;

 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep the
 initializer in the include file so this is primarily a stylistic question.
 Should we keep the output as is, or remove the initializer? My personal
 preference is to remove the initializer but I think the community should
 decide.

 Another question that has come up pertains to the reason for the
 original implementation of DI generation, inlining. According to what
 I've read on these newsgroups and various other sources, DI generation
 is supposed to include the implementation for some small functions that
 would be good inlining candidates, however, it looks like is actually
 happening is that all DMD does is check to see if there are any cases
 where the compiler would fail if it attempted to inline the function. As
 long as the compiler can compile it, it gets thrown into the DI file,
 regardless of size. My current patches never include the implementation,
 and I think that for most people this is a reasonable solution, if not
 ideal. All of the people I've talked to seemed to agree. What do you
 think? Does this work for you? Should there be a way to specify the
 maximum size of an inline function? NOTE: Doing this would require at
 least a command line switch and probably some significant reworking of
 the function symbol exporter. As such it'd take a lot more time to get
 into to D; I'd recommend implementing the simple solution first then
 adding this only if it's requested by a significant number of people.

 The next question is primarily directed at Walter, but anybody who knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration()
 as I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is
 declared in a module (with no surrounding class) or in a struct, it
 always returns null, regardless of whether or not it's actually a
 function. Is there any way to determine if the symbol is a function when
 it's not a class member? NOTE: As near as I can tell, it is actually a
 FuncDeclaration.

 The final bit of DI generation revolves around the handling of protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.

 Thank you all for taking the time to read and chime in on this!

Dec 14 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/14/2011 08:44 PM, Paulo Pinto wrote:
 Thanks for the nice work.

 Personally I would like that DI files would work like the
 interfaces work in another module aware languages.

 The interface is just that, the interface. Everything that
 has to do with code or variable initialization is part of the
 implementation part.

 --
 Paulo

I agree, but sometimes code is part of the interface, eg if it is supposed to be usable in CTFE.
Dec 14 2011
prev sibling next sibling parent "Adam Wilson" <flyboynw gmail.com> writes:
On Wed, 14 Dec 2011 10:58:30 -0800, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 12/14/2011 07:47 PM, Adam Wilson wrote:
 Hello everyone,

 As some of you may be aware I have been working on improvements to the
 .di file generation capabilities in D

Nice!
 and I've run across a few things
 that I think should be put to the community.

 The first involves the handling of variable instantiation. Say you
 create the following member variable in a class:

 export int Foo = 1;

 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep the
 initializer in the include file so this is primarily a stylistic  
 question.
 Should we keep the output as is, or remove the initializer? My personal
 preference is to remove the initializer but I think the community should
 decide.

 Another question that has come up pertains to the reason for the
 original implementation of DI generation, inlining. According to what
 I've read on these newsgroups and various other sources, DI generation
 is supposed to include the implementation for some small functions that
 would be good inlining candidates, however, it looks like is actually
 happening is that all DMD does is check to see if there are any cases
 where the compiler would fail if it attempted to inline the function. As
 long as the compiler can compile it, it gets thrown into the DI file,
 regardless of size. My current patches never include the implementation,
 and I think that for most people this is a reasonable solution, if not
 ideal. All of the people I've talked to seemed to agree. What do you
 think? Does this work for you?

Yes, it is always possible to include the function bodies manually or to compile the modules together for release mode if inlining is that important. For now, .di generation should ideally just work.
 Should there be a way to specify the
 maximum size of an inline function? NOTE: Doing this would require at
 least a command line switch and probably some significant reworking of
 the function symbol exporter. As such it'd take a lot more time to get
 into to D; I'd recommend implementing the simple solution first then
 adding this only if it's requested by a significant number of people.

 The next question is primarily directed at Walter, but anybody who knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration()
 as I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is
 declared in a module (with no surrounding class) or in a struct, it
 always returns null, regardless of whether or not it's actually a
 function. Is there any way to determine if the symbol is a function when
 it's not a class member? NOTE: As near as I can tell, it is actually a
 FuncDeclaration.

 The final bit of DI generation revolves around the handling of protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.

 Thank you all for taking the time to read and chime in on this!

How will your patch handle top level string mixins/static if's/version declarations?

At the moment, it doesn't do anything with them that I know off, but I don't know enough about how the compiler handles those constructs to give a good answer. Although if you have a piece of code that you can share for testing against my patches, i'll let you know. -- Adam Wilson Project Coordinator The Horizon Project http://www.thehorizonproject.org/
Dec 14 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, December 14, 2011 10:47:17 Adam Wilson wrote:
 Hello everyone,
 
 As some of you may be aware I have been working on improvements to the .di
 file generation capabilities in D and I've run across a few things that I
 think should be put to the community.
 
 The first involves the handling of variable instantiation. Say you create
 the following member variable in a class:
 
 export int Foo = 1;
 
 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep the
 initializer in the include file so this is primarily a stylistic question.
 Should we keep the output as is, or remove the initializer? My personal
 preference is to remove the initializer but I think the community should
 decide.
 
 Another question that has come up pertains to the reason for the original
 implementation of DI generation, inlining. According to what I've read on
 these newsgroups and various other sources, DI generation is supposed to
 include the implementation for some small functions that would be good
 inlining candidates, however, it looks like is actually happening is that
 all DMD does is check to see if there are any cases where the compiler
 would fail if it attempted to inline the function. As long as the compiler
 can compile it, it gets thrown into the DI file, regardless of size. My
 current patches never include the implementation, and I think that for
 most people this is a reasonable solution, if not ideal. All of the people
 I've talked to seemed to agree. What do you think? Does this work for you?
 Should there be a way to specify the maximum size of an inline function?
 NOTE: Doing this would require at least a command line switch and probably
 some significant reworking of the function symbol exporter. As such it'd
 take a lot more time to get into to D; I'd recommend implementing the
 simple solution first then adding this only if it's requested by a
 significant number of people.
 
 The next question is primarily directed at Walter, but anybody who knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration() as
 I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is declared
 in a module (with no surrounding class) or in a struct, it always returns
 null, regardless of whether or not it's actually a function. Is there any
 way to determine if the symbol is a function when it's not a class member?
 NOTE: As near as I can tell, it is actually a FuncDeclaration.
 
 The final bit of DI generation revolves around the handling of protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.
 
 Thank you all for taking the time to read and chime in on this!

Considering that you must have the bodies of functions to do either inlining or CTFE, stripping _anything_ from a .di file carries a definite cost. Now, maybe large functions shouldn't be put in there, but certainly anything which could be reasonably inlined should be, and depending on what you're doing with CTFE, you're going to need the big ones anyway - though that depends on the particular usage more than inlining does, so having to add the function bodies manually for CTFE isn't as big a deal as it would be for inlining. Also, _all_ templated _anything_ has to be put in the .di file, and a lot of stuff tends to be templated in D (especially in the standard library), so it's pretty easy to need to put a large portion of your code in the .di file anyway. Personally, I think that .di files aren't a great idea in general, precisely because of the issues with inlining and CTFE, so I never use them. They generally complicate things needlessly. In some cases, it probably does make sense to use them (e.g. you have a very large project that needs the additional boost in compilation speed or if you have a number of classes with large function bodies which aren't going to be used with CTFE and can't be inlined, because they're virtual), but in general, I just don't think that they're worth messing with - especially when you consider having to keep the .di and .d files in sync. dmd is very fast compiler, and I really think that in the majority of cases, there's not really any point to .di files. And when you _do_ use them, a lot of code has to be in them anyway, or you lose the ability to inline or use CTFE, which would harm performance and impede what your code can do. And if you're using templates much, then it all ends up in the .di file anyway. - Jonathan M Davis
Dec 14 2011
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/14/2011 09:24 PM, Adam D. Ruppe wrote:
 On Wednesday, 14 December 2011 at 20:14:42 UTC, Jonathan M Davis wrote:
 Considering that you must have the bodies of functions to do either
 inlining or CTFE, stripping _anything_ from a .di file carries a
 definite cost.

I agree with you in general. I think the main use of .di files is for closed source libraries... which means we should probably go with putting as little in as possible. If you want it all, use your .d files directly. If you want a closed source lib, go with .di, then add back only what you want to release the source for (templates, ctfe functions, inline things) manually.

If a project grows sufficiently large, the possibility of having separate compilation is certainly important too. The compilation of my current project takes about 1.3s. If I compile every module on its own, I get a compile time of ~6s. That is because the semantic analysis of the code involves a fair bit of CTFE, and imported modules need to be semantically analyzed to a certain extent. Autogenerated .di files should work in a way that reduces this cost so that an efficient incremental compilation setup gets easy. If the autogenerated .di file contains the CTFE'd information, compilation gets a lot faster.
Dec 14 2011
prev sibling parent Paulo Pinto <pjmlp progtools.org> writes:
Am 14.12.2011 21:13, schrieb Jonathan M Davis:
 Also, _all_ templated _anything_ has to be put in the .di file, and a lot of

pretty easy to need to put a large portion of your code in the .di file anyway.

I think that Modula-3, Eiffel and Ada don't have issues with having "template" declaration in the interface part, with the definition being done in the implementation part. Then again, what they support is what is more commonly known as generics. I imagine you mean that metaprogramming requires the template code to be in the .di file as well, right? -- Paulo
Dec 14 2011
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 14 December 2011 at 20:14:42 UTC, Jonathan M Davis 
wrote:
 Considering that you must have the bodies of functions to do 
 either inlining or CTFE, stripping _anything_ from a .di file 
 carries a definite cost.

I agree with you in general. I think the main use of .di files is for closed source libraries... which means we should probably go with putting as little in as possible. If you want it all, use your .d files directly. If you want a closed source lib, go with .di, then add back only what you want to release the source for (templates, ctfe functions, inline things) manually.
Dec 14 2011
prev sibling next sibling parent "Adam Wilson" <flyboynw gmail.com> writes:
On Wed, 14 Dec 2011 12:30:33 -0800, Timon Gehr <timon.gehr gmx.ch> wrote:

 On 12/14/2011 09:05 PM, Adam Wilson wrote:
 On Wed, 14 Dec 2011 10:58:30 -0800, Timon Gehr <timon.gehr gmx.ch>  
 wrote:

 On 12/14/2011 07:47 PM, Adam Wilson wrote:
 Hello everyone,

 As some of you may be aware I have been working on improvements to the
 .di file generation capabilities in D

Nice!
 and I've run across a few things
 that I think should be put to the community.

 The first involves the handling of variable instantiation. Say you
 create the following member variable in a class:

 export int Foo = 1;

 Currently the di generation output is identical to the above line. My
 understanding is that, similar to C/C++, D doesn't care if you keep  
 the
 initializer in the include file so this is primarily a stylistic
 question.
 Should we keep the output as is, or remove the initializer? My  
 personal
 preference is to remove the initializer but I think the community  
 should
 decide.

 Another question that has come up pertains to the reason for the
 original implementation of DI generation, inlining. According to what
 I've read on these newsgroups and various other sources, DI generation
 is supposed to include the implementation for some small functions  
 that
 would be good inlining candidates, however, it looks like is actually
 happening is that all DMD does is check to see if there are any cases
 where the compiler would fail if it attempted to inline the function.  
 As
 long as the compiler can compile it, it gets thrown into the DI file,
 regardless of size. My current patches never include the  
 implementation,
 and I think that for most people this is a reasonable solution, if not
 ideal. All of the people I've talked to seemed to agree. What do you
 think? Does this work for you?

Yes, it is always possible to include the function bodies manually or to compile the modules together for release mode if inlining is that important. For now, .di generation should ideally just work.
 Should there be a way to specify the
 maximum size of an inline function? NOTE: Doing this would require at
 least a command line switch and probably some significant reworking of
 the function symbol exporter. As such it'd take a lot more time to get
 into to D; I'd recommend implementing the simple solution first then
 adding this only if it's requested by a significant number of people.

 The next question is primarily directed at Walter, but anybody who  
 knows
 anything about the compiler internals is welcome to chime in. For
 functions defined in Class and Interfaces, calling isFuncDeclaration()
 as I iterate through the symbol tree works as expected and returns the
 Function. However, when I try to call that on a function that is
 declared in a module (with no surrounding class) or in a struct, it
 always returns null, regardless of whether or not it's actually a
 function. Is there any way to determine if the symbol is a function  
 when
 it's not a class member? NOTE: As near as I can tell, it is actually a
 FuncDeclaration.

 The final bit of DI generation revolves around the handling of  
 protected
 functions in exported classes. But that's better suited to a separate
 topic as that involves the general design of scoping in D2 and isn't
 limited to DI generation. I'll be posting another topic on that soon.

 Thank you all for taking the time to read and chime in on this!

How will your patch handle top level string mixins/static if's/version declarations?

At the moment, it doesn't do anything with them that I know off, but I don't know enough about how the compiler handles those constructs to give a good answer. Although if you have a piece of code that you can share for testing against my patches, i'll let you know.

I think currently it just creates a corrupted .di file if it encounters the construct. Ideally it would just expand them to make their compilation faster.

We'll have to complain loudly enough to Walter about that then. I'm not familiar enough with the compiler internals to tackle that issue myself. :-) -- Adam Wilson Project Coordinator The Horizon Project http://www.thehorizonproject.org/
Dec 14 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, December 14, 2011 21:37:14 Timon Gehr wrote:
 On 12/14/2011 09:24 PM, Adam D. Ruppe wrote:
 On Wednesday, 14 December 2011 at 20:14:42 UTC, Jonathan M Davis wrote:
 Considering that you must have the bodies of functions to do either
 inlining or CTFE, stripping _anything_ from a .di file carries a
 definite cost.

I agree with you in general. I think the main use of .di files is for closed source libraries... which means we should probably go with putting as little in as possible. If you want it all, use your .d files directly. If you want a closed source lib, go with .di, then add back only what you want to release the source for (templates, ctfe functions, inline things) manually.

If a project grows sufficiently large, the possibility of having separate compilation is certainly important too. The compilation of my current project takes about 1.3s. If I compile every module on its own, I get a compile time of ~6s. That is because the semantic analysis of the code involves a fair bit of CTFE, and imported modules need to be semantically analyzed to a certain extent. Autogenerated .di files should work in a way that reduces this cost so that an efficient incremental compilation setup gets easy. If the autogenerated .di file contains the CTFE'd information, compilation gets a lot faster.

But it doesn't contain any CTFE information beyond the source code itself. There's no question that .di files could be improved to work better with regards to CTFE, but that would require redesigning .di files on some level, which probably can't be done for D2 at this point. - Jonathan M Davis
Dec 14 2011
prev sibling next sibling parent "Adam Wilson" <flyboynw gmail.com> writes:
On Wed, 14 Dec 2011 15:26:05 -0800, Paulo Pinto <pjmlp progtools.org>  
wrote:

 Am 14.12.2011 21:13, schrieb Jonathan M Davis:
 Also, _all_ templated _anything_ has to be put in the .di file, and a  
 lot of

so it's pretty easy to need to put a large portion of your code in the .di file anyway.

I think that Modula-3, Eiffel and Ada don't have issues with having "template" declaration in the interface part, with the definition being done in the implementation part. Then again, what they support is what is more commonly known as generics. I imagine you mean that metaprogramming requires the template code to be in the .di file as well, right? -- Paulo

As a note for this discussion, when you export stuff via DI gen, it includes templates. In the cases of classes it wraps the class inside the template. My patches don't effect this template code, they work on members. The only potential issue I can see is that my patch would execute after a function level template and leave the template hanging without the corresponding function. Does anyone have some test code that I can run to verify this behavior? -- Adam Wilson Project Coordinator The Horizon Project http://www.thehorizonproject.org/
Dec 14 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, December 15, 2011 00:26:05 Paulo Pinto wrote:
 Am 14.12.2011 21:13, schrieb Jonathan M Davis:
 Also, _all_ templated _anything_ has to be put in the .di file, and a
 lot of> 

so it's pretty easy to need to put a large portion of your code in the .di file anyway.

"template" declaration in the interface part, with the definition being done in the implementation part. Then again, what they support is what is more commonly known as generics. I imagine you mean that metaprogramming requires the template code to be in the .di file as well, right?

As similar as they may appear, templates and generics are completely different. With templates, you're literally generating code, and the compiler needs to full source of the template to generate that code. Generics typically means that you have one set of code which is just used with different types (typically enabled by the fact that all of the type have a base class which they share). So, with generics, you can separate interface and implementation, but that's impossible with templates (C++ has the same issue). The code which is generated could vary drastically depending on what you try and instantiate a template with, unlike with generics. And ultimately, what it comes down to is the fact that templates literally generate code, so their full source is required. - Jonathan M Davis
Dec 14 2011
parent Paulo Pinto <pjmlp progtools.org> writes:
Sorry, but that is not correct.

I don't know if that is your case, but many people confuse generics with the
dumb implementation that Java has.

The languages that support proper generics, have the compiler store a kind of
code template in the module with placeholders. This code is then extracted from
the module during compile time and the placeholders get replaced by the code
required for the specific type.

One reason why the C++ templates are the way they are, is that C++ designers
always wanted to support the primitive compiler/linker toolchains in UNIX. This
is not an issue in languages that have proper module support without toolchain
constraints.

--
Paulo


Jonathan M Davis Wrote:

 On Thursday, December 15, 2011 00:26:05 Paulo Pinto wrote:
 Am 14.12.2011 21:13, schrieb Jonathan M Davis:
 Also, _all_ templated _anything_ has to be put in the .di file, and a
 lot of> 

so it's pretty easy to need to put a large portion of your code in the .di file anyway.

"template" declaration in the interface part, with the definition being done in the implementation part. Then again, what they support is what is more commonly known as generics. I imagine you mean that metaprogramming requires the template code to be in the .di file as well, right?

As similar as they may appear, templates and generics are completely different. With templates, you're literally generating code, and the compiler needs to full source of the template to generate that code. Generics typically means that you have one set of code which is just used with different types (typically enabled by the fact that all of the type have a base class which they share). So, with generics, you can separate interface and implementation, but that's impossible with templates (C++ has the same issue). The code which is generated could vary drastically depending on what you try and instantiate a template with, unlike with generics. And ultimately, what it comes down to is the fact that templates literally generate code, so their full source is required. - Jonathan M Davis

Dec 14 2011