www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Problems with Template codegen

reply kris <foo bar.com> writes:
At this time, D templates are a bit finicky when it comes to argument 
matching -- IFTI matching, to be explicit. For example:

# uint locate(T) (T[] source, T match, uint start=0);
#
# locate ("wumpus", 'p', 1);

will not compile because '1' is an integer literal, and does not match 
the template parameter 'uint'.

To get around this, template writers will revert to tricks like this one:

# uint locate(T) (T[] source, T match, uint start=0);
#
# uint locate(T, U=uint) (T[] source, T match, U start=0)
# {
#     return locate!(T) (source, match, start);
# }
#
# locate ("wumpus", 'p', 1);


See what's going on? There's a stub added, which marshalls (for want of 
a better term) the 'int' argument  across. This is done to (a) permit 
use of both int & uint arguments and (b) to avoid template duplication 
for both int and uint types.

So, that's a current shortcoming of IFTI -- but it's one that we hope 
will be fixed. Moving onto the primary concern ...

As one would expect, the DM compiler generates code for the stub to 
re-push the arguments and call the /real/ implementation. However, in 
/all/ cases we really want to eliminate the stub since it is nothing but 
a pass-through call; one generated to workaround what seems to be an 
IFTI limitation.

Unfortunately, the DM tools will remove the stub /only/ when you use the 
-inline switch. This is a very powerful switch, causing all kinds of 
inlining to occur -- in some cases, things which many engineers would 
balk at. Inline is often just too /big/ a switch to pull.

However, we'd still like darned stubs to be removed from the codegen. 
How do we get that to happen?
Feb 04 2007
next sibling parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
kris wrote:
 At this time, D templates are a bit finicky when it comes to argument 
 matching -- IFTI matching, to be explicit. For example:
 
 # uint locate(T) (T[] source, T match, uint start=0);
 #
 # locate ("wumpus", 'p', 1);
 
 will not compile because '1' is an integer literal, and does not match 
 the template parameter 'uint'.
 
 To get around this, template writers will revert to tricks like this one:
 
 # uint locate(T) (T[] source, T match, uint start=0);
 #
 # uint locate(T, U=uint) (T[] source, T match, U start=0)
 # {
 #     return locate!(T) (source, match, start);
 # }
 #
 # locate ("wumpus", 'p', 1);
 
 
 See what's going on? There's a stub added, which marshalls (for want of 
 a better term) the 'int' argument  across. This is done to (a) permit 
 use of both int & uint arguments and (b) to avoid template duplication 
 for both int and uint types.
 
 So, that's a current shortcoming of IFTI -- but it's one that we hope 
 will be fixed. Moving onto the primary concern ...
 
 As one would expect, the DM compiler generates code for the stub to 
 re-push the arguments and call the /real/ implementation. However, in 
 /all/ cases we really want to eliminate the stub since it is nothing but 
 a pass-through call; one generated to workaround what seems to be an 
 IFTI limitation.
 
 Unfortunately, the DM tools will remove the stub /only/ when you use the 
 -inline switch. This is a very powerful switch, causing all kinds of 
 inlining to occur -- in some cases, things which many engineers would 
 balk at. Inline is often just too /big/ a switch to pull.
 
 However, we'd still like darned stubs to be removed from the codegen. 
 How do we get that to happen?

One notion would be to use the (T, U=uint) notation for the 'real' template and leave the stub out, but it defeats the original intent somewhat and doesn't really *solve* the problem. I'd say IFTI just needs to incorporate implicit casting rules such as int->uint and that would be a solution. -- Chris Nicholson-Sauls
Feb 04 2007
parent kris <foo bar.com> writes:
Chris Nicholson-Sauls wrote:
 kris wrote:
 
 At this time, D templates are a bit finicky when it comes to argument 
 matching -- IFTI matching, to be explicit. For example:

 # uint locate(T) (T[] source, T match, uint start=0);
 #
 # locate ("wumpus", 'p', 1);

 will not compile because '1' is an integer literal, and does not match 
 the template parameter 'uint'.

 To get around this, template writers will revert to tricks like this one:

 # uint locate(T) (T[] source, T match, uint start=0);
 #
 # uint locate(T, U=uint) (T[] source, T match, U start=0)
 # {
 #     return locate!(T) (source, match, start);
 # }
 #
 # locate ("wumpus", 'p', 1);


 See what's going on? There's a stub added, which marshalls (for want 
 of a better term) the 'int' argument  across. This is done to (a) 
 permit use of both int & uint arguments and (b) to avoid template 
 duplication for both int and uint types.

 So, that's a current shortcoming of IFTI -- but it's one that we hope 
 will be fixed. Moving onto the primary concern ...

 As one would expect, the DM compiler generates code for the stub to 
 re-push the arguments and call the /real/ implementation. However, in 
 /all/ cases we really want to eliminate the stub since it is nothing 
 but a pass-through call; one generated to workaround what seems to be 
 an IFTI limitation.

 Unfortunately, the DM tools will remove the stub /only/ when you use 
 the -inline switch. This is a very powerful switch, causing all kinds 
 of inlining to occur -- in some cases, things which many engineers 
 would balk at. Inline is often just too /big/ a switch to pull.

 However, we'd still like darned stubs to be removed from the codegen. 
 How do we get that to happen?

One notion would be to use the (T, U=uint) notation for the 'real' template and leave the stub out, but it defeats the original intent somewhat and doesn't really *solve* the problem.

That's right, because you wind up with multiple instantiations of the same template, just for the same of supporting int type-variations.
 I'd say IFTI just 
 needs to incorporate implicit casting rules such as int->uint and that 
 would be a solution.

Right. But are we supposed to do in the interim? - Kris
Feb 05 2007
prev sibling parent Derek Parnell <derek nomail.afraid.org> writes:
On Sun, 04 Feb 2007 16:50:02 -0800, kris wrote:

 At this time, D templates are a bit finicky when it comes to argument 
 matching -- IFTI matching, to be explicit. For example:
 
 # uint locate(T) (T[] source, T match, uint start=0);
 #
 # locate ("wumpus", 'p', 1);
 
 will not compile because '1' is an integer literal, and does not match 
 the template parameter 'uint'.

The way I'd prefer D to work is rather than seeing the 1 and deciding that this literal must only be an *int*, it could recognize that the literal *1* is ambiguous, as it could be stored as one of a number of integer forms. It would then search for which signatures match "integer" rather than "int", and if there is only one, resolve the literal's ambiguity by using the sole matching signature. Of course, if there are multiple matching signatures then it needs to alert the coder of the ambiguity and have them sort it out by explicit casts. I base my opinion on the need for programming languages and compilers to be helpful to people, as a first priority. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 5/02/2007 1:37:33 PM
Feb 04 2007