Don wrote:
bearophile wrote:
I have also tested the semantics of nested function purity:
import std.c.stdio: printf;
import std.conv: to;
pure int double_sqr(int x) {
pure int sqr(int y) { return y * y; }
return sqr(x) + sqr(x);
}
void main(string[] args) {
int x = args.length == 2 ? to!(int)(args[1]) : 10;
int y = double_sqr(x) + double_sqr(x);
printf("4 * x * x = %d\n", y);
}
Compiled without inlining:
-O -release
double_sqr.sqr:
mov EAX,4[ESP]
imul EAX,EAX
ret 4
double_sqr:
L0: push EAX
push EAX
xor EAX,EAX
call near ptr double_sqr.sqr
push EAX
sub ESP,4
xor EAX,EAX
push dword ptr 8[ESP]
call near ptr double_sqr.sqr
add ESP,4
mov ECX,EAX
pop EAX
add EAX,ECX
pop ECX
ret
main:
L0: push EAX
cmp dword ptr 8[ESP],2
jne L1D
mov EDX,0Ch[ESP]
mov EAX,8[ESP]
push dword ptr 0Ch[EDX]
push dword ptr 8[EDX]
call near ptr to!(int)()
jmp short L22
L1D: mov EAX,0Ah
L22: call near ptr double_sqr
add EAX,EAX
mov ECX,offset FLAT:_DATA
push EAX
push ECX
call near ptr printf
There's one call to double_sqr but unfortunately two to double_sqr.sqr.
Bye,
bearophile
Yes. Actually, marking a nested function as pure doesn't make much sense.
It's entirely equivalent to moving it outside the function; a nested
pure function shouldn't be able to access any members of the enclosing
function, otherwise it's not pure. But DMD doesn't enforce that, and so
it creates inefficient and possibly buggy code.
The bug is bugzilla 2807.
I'm not sure that nested pure member functions should be legal.
And it turns out that sqr() isn't actually pure, in the same way that it
wasn't nothrow in your first example. The 'pure' marker is silently
being ignored. If you put the 'pure' at the end, you get bug 2807.
--