www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - More 'pure' experiments

I am doing some more experiments with pure functions in D2, I have seen this
compiles, but fails at runtime in some non fully clear way (DMD 2.030):

import std.stdio: writeln;
import std.c.stdlib: malloc;

pure foo(int n) {
    int* p = cast(int*)malloc(int.sizeof * n);
    if (p == null)
        return -1;

    int[] arr = p[0 .. n];
    foreach (i, ref el; arr)
        el = i;

    int tot;
    foreach (el; arr)
        tot += el;

    return tot;
}

void main() {
    enum int N = 2_000_000_000;
    writeln(foo(N) * foo(N));
}

---------------------------

Then I have tried with alloca() too, it allocates memory on the stack, so it
may be used inside pure functions:

import std.stdio: writeln;
import std.c.stdlib: alloca;

pure int foo(int n) {
    int* p = cast(int*)alloca(int.sizeof * n);
    if (p == null)
        return -1;

    int[] arr = p[0 .. n];
    foreach (i, ref el; arr)
        el = i;

    int tot;
    foreach (el; arr)
        tot += el;

    return tot;
}

void main() {
    enum int N = 2_000;
    writeln(foo(N) * foo(N));
}

But unfortunately it seems alloca() isn't seen as pure:
pure_test2.d(5): Error: pure function 'foo' cannot call impure function 'alloca'

---------------------------

Then I have tried exceptions, they are allowed in pure functions, but I am not
sure this is safe:


import std.stdio: writeln;

pure int sqr(int n) {
    throw new Exception("exception in foo()");
    return n * n;
}

void main() {
    enum int N = 20;
    writeln(sqr(N) * sqr(N));
}


Its (cleaned up) ASM:

sqr:
L0:     push    EAX
        mov ECX,offset FLAT:_D9Exception7__ClassZ
        push    ECX
        call    near ptr __d_newclass
        add ESP,4
        push    dword ptr FLAT:_DATA[01Ch]
        push    dword ptr FLAT:_DATA[018h]
        push    0
        call    near ptr
_D6object9Exception6__ctorMFAyaC6object9ThrowableZC9Exception
        push    EAX
        call    near ptr __d_throw 4
        mov EAX,[ESP]
        imul    EAX,EAX
        pop ECX
        ret

main:
L0:     push    EAX
        mov EAX,014h
        call    near ptr sqr
        mov ECX,EAX
        imul    ECX
        push    EAX
        mov EAX,offset FLAT:_D3std5stdio6stdoutS3std5stdio4File
        push    0Ah
        call    near ptr _D3std5stdio4File14__T5writeTiTaZ5writeMFiaZv
        xor EAX,EAX
        pop ECX
        ret

Bye,
bearophile
Jun 16 2009