Programming Language for Games, part 3
bearophile via Digitalmars-d
digitalmars-d at puremagic.com
Sat Nov 1 15:26:16 PDT 2014
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
More information about the Digitalmars-d
mailing list