This is a possible enhancement request for DMD. I am not sure about the 
consequences of this, so this is currently not in Bugzilla, I look for opinions.

DMD currently runs functions at compile time only if their call is in a context 
where a compile-time value is expected, to avoid troubles. C++0X uses a keyword 
to avoid those problems.

[-----------------

Little box:

Time ago I have heard that "enum" is useless and const/immutable suffice. So if 
"enum" gets removed from D how do you tell apart the desire to run a function 
(not a global call) at compile time from the desire to run it at run time and 
assign its result to a run-time constant value?

int bar(int x) {
    return x;
}
void main() {
    enum b1 = bar(10); // runs at compile-time
    const b2 = bar(20); // doesn't run at compile-time    
}

-----------------]

DMD is able to run contracts too at compile-time, as you see in this program 
(at the r1 enum):


import std.ctype: isdigit;
int foo(string text, int x)
in {
    assert(x >= 0 && x < text.length);
    foreach (c; text[0 .. x])
        assert(isdigit(c));
} body {
    return 0;
}
enum r1 = foo("123xxx", 4); // Error: assert(isdigit(cast(dchar)c)) failed
void main(string[] args) {
    auto r2 = foo(args[2], (cast(int)args.length) - 5);
    auto r3 = foo("123xxx", 4);
}


test.d(3): Error: assert(x > 0) failed
test.d(7): Error: cannot evaluate foo(-1) at compile time
test.d(7): Error: cannot evaluate foo(-1) at compile time


Given that pre-conditions are meant to run fast and to be (nearly) pure, this 
is my idea: when you call a function with all arguments known at compile time 
(as at the r3 variable) the compiler runs just the pre-condition of that 
function at compile-time (and not its body and post-condition).

The advantage is some bugs are caught at compile-time, and the compiler is kept 
simple (I'd like contracts to be verified statically in more situations, but 
this requires a more complex compiler). The disadvantage is longer compilation 
times, and troubles caused by pre-conditions that can't really run at 
compile-time (like a precondion that uses a compiler intrinsic). A way to solve 
this last problem is to not raise an error if a pre-condition can't run at 
compile-time, and just ignore it, and let it later run normally at run-time.

The variable r2 is a situation where not all arguments of foo() are known at 
compile-time, so here the foo pre-condition is not run.


(Note: the variable r2 is a situation where one argument of foo is known at 
run-time, and in this case the pre-condition contains a part 
(assert(x>=0&&x<text.length)) that's able to use this information to catch a 
bug. This is a possible improvement of the idea is to perform this partial 
test. This looks less easy to implement, so it's not important).

Bye,
bearophile

Reply via email to