Nesting in pure functions
Don
nospam at nospam.com
Mon Apr 6 02:53:22 PDT 2009
Don wrote:
> bearophile wrote:
>> This post was originally meant for digitalmars.D.learn, but maybe it
>> can interest more people here.
>>
>> Now that the D1/D2 zips have a better internal structure and don't
>> require DMC anymore I am more free to use D2 more, so I have tried to
>> understand how the optimization of pure functions works.
>>
>> So I have written this toy program that computes:
>> ((x*x)+(x*x)) + ((x*x)+(x*x))
>>
>>
>> import std.c.stdio: printf;
>> import std.conv: toInt;
>>
>> pure int double_sqr(int x) {
>> int y, z;
>> void do_sqr() { y *= y; }
>> y = x;
>> do_sqr();
>> z += y;
>> y = x;
>> do_sqr();
>> z += y;
>> return z;
>> }
>>
>> void main(string[] args) {
>> int x = args.length == 2 ? toInt(args[1]) : 10;
>> int y = double_sqr(x) + double_sqr(x);
>> printf("4 * x * x = %d\n", y);
>> }
>>
>
>> double_sqr() is a pure function. do_sqr() isn't a pure function, but
>> it has no side effects outside double_sqr(), so double_sqr() is
>> globally pure still. But the compiler (dmd v2.027) doesn't accept it
>> (notice the strange blank line in the middle):
>
> There's some compiler bugs. Try:
>
> void do_sqr() pure { y *= y; }
>
> and it compiles, but generates wrong code.
> pure void do_sqr() doesn't compile. Nothrow behaves the same.
> Compare with bugzilla 2694.
>
> But this one works:
>
> pure int double_sqr(int x) {
> int z;
> int do_sqr(int y) pure { return y*y; }
> z = do_sqr(x);
> z += do_sqr(x);
> return z;
> }
In fact, the fact that it accepts 'pure' on nested functions is probably
a bug. Patch:
In expression.c, around line 1100, you can disable the purity check if
it's a nested function:
void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
{
if (sc->func && sc->func->isPure() && !sc->intypeof &&
(!f->isNested() && !f->isPure()))
-----
But, this still isn't enough, because it doesn't check the nested
functions for purity. Rather than checking if the function is pure,
FuncDeclaration needs 'ultimatelyPure' and 'ultimatelyNothrow' members,
which are assigned when the declaration is encountered. Almost all
purity checks need to be made against the 'ultimatelyPure' member. (But
things like purity of delegates would be made from the 'pure' member
rather than the 'ultimately pure' member).
More information about the Digitalmars-d
mailing list