Thread overview
Error: non-constant expression...
Nov 26, 2010
spir
Nov 26, 2010
bearophile
Nov 26, 2010
bearophile
Nov 26, 2010
bearophile
Nov 26, 2010
spir
November 26, 2010
Hello,

void f () {
    static string[string] map = ["1":"un", "2":"du", "3":"tri"];
}
==>
Error: non-constant expression ["1":"un","2":"du","3":"tri"]

I do not understand what is meant, and what I should do. I need 'static', it's a constant value for the func.
"static int[] a = [1,2,3];" is OK. Where's the difference?
Also tried const() and immutable(), who knows?, but no way. Search does not bring anything for "non-constant expression". (Also: pointer to dmd error messages welcome.)

Thank you all,
Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com

November 26, 2010
spir:

> void f () {
>     static string[string] map = ["1":"un", "2":"du", "3":"tri"];
> }
> ==>
> Error: non-constant expression ["1":"un","2":"du","3":"tri"]
> 
> I do not understand what is meant, and what I should do.

Associative arrays are run-time things... well, enum associative arrays are compile-time things in theory, but there is a compiler bug here (I think an enum struct gets re-evaluated each time).

So this works, but I think it's not efficient:

void foo() {
    enum string[string] map = ["1":"un", "2":"du", "3":"tri"];
}


> I need 'static', it's a constant value for the func.

A static variable in a function is a global value that is visible only inside that function and its sub-scopes (this is not always true in DMD, but I think these cases are bugs).


> "static int[] a = [1,2,3];" is OK. Where's the difference?
> Also tried const() and immutable(), who knows?, but no way. Search does not bring anything for "non-constant expression".

Both const and immutable work:

void foo() {
    immutable string[string] map1 = ["1":"un", "2":"du", "3":"tri"];
    const string[string] map2 = ["1":"un", "2":"du", "3":"tri"];
}

But those map1 and map2 aren't static, this is not good because I think those AAs get initialized at each function call (despite only once is enough here). To avoid that you may use:

immutable string[string] fooMap;
static this() {
    fooMap = ["1":"un", "2":"du", "3":"tri"];
}
void foo() {
    // ....
}

But the disadvantage is that fooMap is accessible outside foo() too.
In my mind there is some confusion about all this. Other people may give you better answers.


> (Also: pointer to dmd error messages welcome.)

I don't know any complete list of DMD errors.

Bye,
bearophile
November 26, 2010
> In my mind there is some confusion about all this. Other people may give you better answers.

A solution in such situations is to take a look at the asm, that has confirmed my ideas:


string first_function(string k) {
    immutable string[string] map1 = ["bar" : "spam"];
    return map1[k];
}
string second_function(string k) {
    const string[string] map2 = ["bar" : "spam"];
    return map2[k];
}
string third_function(string k) {
    enum string[string] map3 = ["bar" : "spam"];
    return map3[k];
}
string fourth_function(string k) {
    static enum string[string] map4 = ["bar" : "spam"];
    return map4[k];
}
immutable string[string] map5;
static this() {
    map5 = ["bar" : "spam"];
}
string fifth_function(string k) {
    return map5[k];
}
void main() {}


Compiled with:
DMD 2.050, -O -release -inline

_D5test314first_functionFAyaZAya    comdat
L0:     push    EAX
        mov EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
        mov ECX,offset FLAT:_D16TypeInfo_HAyayAa6__initZ
        push    dword ptr 0Ch[ESP]
        push    dword ptr 0Ch[ESP]
        push    8
        push    EAX
        push    dword ptr FLAT:_DATA[01Ch]
        push    dword ptr FLAT:_DATA[018h]
        push    dword ptr FLAT:_DATA[0Ch]
        push    dword ptr FLAT:_DATA[08h]
        push    1
        push    ECX
        call    near ptr __d_assocarrayliteralT
        add ESP,018h
        push    EAX
        call    near ptr __aaGetRvalue
        mov EDX,4[EAX]
        mov EAX,[EAX]
        add ESP,014h
        pop ECX
        ret 8

_D5test315second_functionFAyaZAya   comdat
L0:     push    EAX
        mov EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
        mov ECX,offset FLAT:_D17TypeInfo_HAyaxAya6__initZ
        push    dword ptr 0Ch[ESP]
        push    dword ptr 0Ch[ESP]
        push    8
        push    EAX
        push    dword ptr FLAT:_DATA[01Ch]
        push    dword ptr FLAT:_DATA[018h]
        push    dword ptr FLAT:_DATA[0Ch]
        push    dword ptr FLAT:_DATA[08h]
        push    1
        push    ECX
        call    near ptr __d_assocarrayliteralT
        add ESP,018h
        push    EAX
        call    near ptr __aaGetRvalue
        mov EDX,4[EAX]
        mov EAX,[EAX]
        add ESP,014h
        pop ECX
        ret 8

_D5test314third_functionFAyaZAya    comdat
L0:     push    EAX
        mov EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
        mov ECX,offset FLAT:_D16TypeInfo_HAyaAya6__initZ
        push    dword ptr 0Ch[ESP]
        push    dword ptr 0Ch[ESP]
        push    8
        push    EAX
        push    dword ptr FLAT:_DATA[01Ch]
        push    dword ptr FLAT:_DATA[018h]
        push    dword ptr FLAT:_DATA[0Ch]
        push    dword ptr FLAT:_DATA[08h]
        push    1
        push    ECX
        call    near ptr __d_assocarrayliteralT
        add ESP,018h
        push    EAX
        call    near ptr __aaGetRvalue
        mov EDX,4[EAX]
        mov EAX,[EAX]
        add ESP,014h
        pop ECX
        ret 8

_D5test315fourth_functionFAyaZAya   comdat
L0:     push    EAX
        mov EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
        mov ECX,offset FLAT:_D16TypeInfo_HAyaAya6__initZ
        push    dword ptr 0Ch[ESP]
        push    dword ptr 0Ch[ESP]
        push    8
        push    EAX
        push    dword ptr FLAT:_DATA[01Ch]
        push    dword ptr FLAT:_DATA[018h]
        push    dword ptr FLAT:_DATA[0Ch]
        push    dword ptr FLAT:_DATA[08h]
        push    1
        push    ECX
        call    near ptr __d_assocarrayliteralT
        add ESP,018h
        push    EAX
        call    near ptr __aaGetRvalue
        mov EDX,4[EAX]
        mov EAX,[EAX]
        add ESP,014h
        pop ECX
        ret 8

_D5test314fifth_functionFAyaZAya    comdat
L0:     push    EAX
        mov EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
        push    dword ptr 0Ch[ESP]
        push    dword ptr 0Ch[ESP]
        push    8
        push    EAX
        push    dword ptr _D5test34map5yHAyaAa
        call    near ptr __aaGetRvalue
        mov EDX,4[EAX]
        mov EAX,[EAX]
        add ESP,014h
        pop ECX
        ret 8


I may add something about this in bugzilla (the problem with enum AAs is already present there).

Bye,
bearophile
November 26, 2010
On Fri, 26 Nov 2010 16:17:10 -0500
bearophile <bearophileHUGS@lycos.com> wrote:

> spir:
> 
> > void f () {
> >     static string[string] map = ["1":"un", "2":"du", "3":"tri"];
> > }
> > ==>
> > Error: non-constant expression ["1":"un","2":"du","3":"tri"]
> > 
> > I do not understand what is meant, and what I should do.
> 
> Associative arrays are run-time things... well, enum associative arrays are compile-time things in theory, but there is a compiler bug here (I think an enum struct gets re-evaluated each time).
> 
> So this works, but I think it's not efficient:
> 
> void foo() {
>     enum string[string] map = ["1":"un", "2":"du", "3":"tri"];
> }
> 
> 
> > I need 'static', it's a constant value for the func.
> 
> A static variable in a function is a global value that is visible only inside that function and its sub-scopes (this is not always true in DMD, but I think these cases are bugs).
> 
> 
> > "static int[] a = [1,2,3];" is OK. Where's the difference?
> > Also tried const() and immutable(), who knows?, but no way. Search does not bring anything for "non-constant expression".
> 
> Both const and immutable work:
> 
> void foo() {
>     immutable string[string] map1 = ["1":"un", "2":"du", "3":"tri"];
>     const string[string] map2 = ["1":"un", "2":"du", "3":"tri"];
> }
> 
> But those map1 and map2 aren't static, this is not good because I think those AAs get initialized at each function call (despite only once is enough here). To avoid that you may use:
> 
> immutable string[string] fooMap;
> static this() {
>     fooMap = ["1":"un", "2":"du", "3":"tri"];
> }
> void foo() {
>     // ....
> }
> 
> But the disadvantage is that fooMap is accessible outside foo() too.
> In my mind there is some confusion about all this. Other people may give you better answers.
> 
> 
> > (Also: pointer to dmd error messages welcome.)
> 
> I don't know any complete list of DMD errors.
> 
> Bye,
> bearophile

All right, thank you Bearophile. I'll define it outside the func (not so bad in my case, as the func itself is not in global scope). And I'll have a look at your asm code tomorrow when my brain is fresher ;-)


Denis
-- -- -- -- -- -- --
vit esse estrany ☣

spir.wikidot.com

November 26, 2010
> I may add something about this in bugzilla (the problem with enum AAs is already present there).

http://d.puremagic.com/issues/show_bug.cgi?id=5279