Walter Bright:

I know you've suggested extensive data flow analysis,

The "static enum" (and related ideas) I've suggested require no flow analysis.


Compile time checking can only be done on compile time arguments (obviously) and template functions can arbitrarily check compile time arguments.

In D it's easy to define a function that you call at compile-time to test that some compile-time data is well formed, I do this often. This is a simple example:


import std.range, std.algorithm;

alias Nibble = ubyte; // 4 bits used.
alias SBox = immutable Nibble[16][8];

private bool _validateSBox(in SBox data) @safe pure nothrow @nogc {
    return data[].all!((ref row) => row[].all!(ub => ub < 16));
}

struct GOST(s...) if (s.length == 1 && s[0]._validateSBox) {
    private static generate(ubyte k)() @safe pure nothrow {
        return k87.length.iota
.map!(i=> (s[0][k][i >> 4] << 4) | s[0][k - 1][i & 0xF])
               .array;
    }

    // ...
}

void main() {
    enum SBox cbrf = [
[ 4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3], [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9], [ 5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11], [ 7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3], [ 6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2], [ 4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14], [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12], [ 1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]];

    GOST!cbrf g;
    // ...
}


But you can run such compile-time tests only on template arguments, or on regular arguments of functions/constructors that are forced to run at compile-time. But for me this is _not_ enough. You can't implement the printf test example he shows (unless you turn the formatting string into a template argument of printf, this introduces template bloat and forbids you to have run-time format strings, or forces you to use two different syntaxes or to create two different print functions).

I'd like a way to run compile-time tests for the arguments of a regular function/constructor if they are known at compile-time.

So here I'd like a way to perform a compile-time test of the arguments of the call of #1 (and to not perform them for the call #2 because its argument is not a compile-time constant) (note that here both foo calls are not run at compile-time, and this is good):


void main() {
    auto x = foo(1); // #1
    int n = bar();
    auto y = foo(n); // #2
}


Currently if you want to do the same thing in D you have to use something like:

void main() {
    auto x = foo(ctEval!test(1)); // #1b
}


(Where "test" is a function that tests the argument and "ctEval" is a little template that forces to run "test" at compile time (here "foo" itself is not run). This becomes not much practical if you have arrays of values, or lot of data, etc, it's not *transparent* at all for the user, and the user can forget to use ctEval).



So this is useful in a large number of cases. If instead of foo() there's a call to a constructor, we become able to verify "game data" at compile time where possible while avoiding templates, and running the actual functions only at run-time.


Probably there are various ways to solve this problem. A lot of time ago I have suggested a "enum precondition":

int foo(in int x)
enum in(x) {
    // Optional enum pre-condition.
} in {
    // Optional normal pre-condition.
} body {
    // Function body.
}


The idea is that if foo is called with literals or compile-time (enum) arguments (here just the x argument is required to be known at compile-time) then it performs the tests inside the enum precondition at compile-time. If the arguments are run-time values then the enum precondition is ignored (and eventually the normal pre condition runs at run-time. Sometimes the two pre-conditions contain the same code or call the same testing function).

If you want to implement this idea very well, you can keep the enum precondition as source code (like with templates) so you can run it at compile-time when the arguments are known at compile-time.

Bye,
bearophile

Reply via email to