Implicit integer casting

bearophile bearophileHUGS at lycos.com
Sun Mar 18 19:30:29 PDT 2012


Andrej Mitrovic:

> Another classic which fails to compile is:
>
> import std.random;
> ubyte c = uniform(0, 256);

It's legit to ask a compiler to help in this case. But currently 
the D type system can't help you here.

The D syntax and type system tell apart sharply run-time values 
from compile-time ones. And the type system doesn't work on 
run-time values.

This is another very simple case that currently the D compilers 
and D language don't signal as error at compile-time (a decent C 
lint is able to find a similar bug at compile time, if you use 
malloc/calloc to allocate the buffer a):

void main() {
     int[] a = new int[5];
     a[10] = 1;
}


So to do that in D you currently need to create a different 
uniform function that accepts compile-time values. If correctly 
implemented this doesn't need a cast to compile:

ubyte c = uniformCT!(0, 256)();


There are some ways to improve this situation. One way is to 
introduce ranged numerical values (like the Ada ones) in the D 
language. This is why implementing them in library code isn't 
good enough. With them you are able to tell the type system that 
a value is in an arbitrarily compile-time-defined range, and 
later the type system is able to use this information for all 
kind of things.

Another harder way to improve the situation is to offer the D 
programmer some way to tell if a regular argument of a regular 
function is known at compile-time (like it being a literal). If 
you use this feature inside a regular function, this function 
essentially becomes a template :-)

In GCC-C there is something related, named 
__builtin_constant_p(exp):
http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

(If you improve that idea you obtain a handmade poor's man 
version of partial compilation, that is useful in a system 
language.)

I think Walter tried a bit to do a simpler version of this, with 
this syntax:

void foo(int x, static int y) {}

Here x is a run-time value and y most be known at compile-time, 
so it's similar to (but this conversion doesn't work if y is an 
array, I never understood why D templates refuse arrays are 
compile-time arguments yet they accept all kind of strings, 
despite strings are a subset of dynamic arrays. And alias 
argument are not the same thing):

void foo(int y)(int x) {}

One difference here is that this template syntax is not 
transparent at the calling point, you must use the template 
instantiation syntax:

foo!(5)(n)

Bye,
bearophile


More information about the Digitalmars-d mailing list