various questions
bearophile
bearophileHUGS at lycos.com
Fri Jul 30 04:03:11 PDT 2010
Jason Spencer:
> I nievely went and replaced "foreach (t; Iota!(str_types.length))"
> with "foreach (t; str_types.length)", since the length of that array
> is known at compile-time. That of course bombed, but I don't quite
> get why. Is the compiler actually evaluating the foreach loop at
> compile time? How could it, when the body makes run-time checks? If
> it's not, why doesn't my change work?
foreach (t; str_types.length) doesn't work because integral values are not iterable. You need a range, collection or tuple.
foreach (t; 0 .. str_types.length) doesn't work in that code because it's a run-time foreach.
The Iota!(n) creates a tuple of the values 0, 1, 2 ... n-1.
The foreach done on a tuple is a static foreach, it's done at compile-time, so my code is a way to perform a compile-time unrolling of the if-goto body. You can see it with this example (normally DMD is not able to perform loop unrolling):
import std.typetuple: TypeTuple;
import std.c.stdio: printf;
template Iota(int stop) {
static if (stop <= 0)
alias TypeTuple!() Iota;
else
alias TypeTuple!(Iota!(stop-1), stop-1) Iota;
}
void main() {
foreach (i; Iota!(5)) {
enum int n = i;
printf("%d\n", n);
}
}
The resulting asm:
__Dmain comdat
push EBX
push 0
mov EAX,offset FLAT:_DATA
push EAX
call near ptr _printf
add ESP,8
push 1
mov ECX,offset FLAT:_DATA
push ECX
call near ptr _printf
add ESP,8
push 2
mov EDX,offset FLAT:_DATA
push EDX
call near ptr _printf
add ESP,8
push 3
mov EBX,offset FLAT:_DATA
push EBX
call near ptr _printf
add ESP,8
push 4
push EBX
call near ptr _printf
add ESP,8
xor EAX,EAX
pop EBX
ret
I suggest you to use a variant of my last version of the code because it contains some asserts and static asserts that improve code safety a bit.
See also this enhancement request of mine:
http://d.puremagic.com/issues/show_bug.cgi?id=4085
Bye,
bearophile
More information about the Digitalmars-d-learn
mailing list