bmx-ng / bcc

A next-generation bcc parser for BlitzMax
zlib License
33 stars 12 forks source link

[Enum] enum.Values() creates new array on each request #524

Open GWRon opened 4 years ago

GWRon commented 4 years ago
SuperStrict
Framework Brl.StandardIO

Enum ETest Flags
    a
    b
End Enum

For local i:int = 0 to 10
  Print ETest.Values()[0].ToString()
Next

Isn't Values() here creating a new array each time?

the generated C code contains:

BBARRAY bbt_=bbEnumValues(_m_untitled2_ETest_BBEnum_impl);
brl_standardio_Print(_m_untitled2_ETest_ToString(((BBINT*)BBARRAYDATA(bbt_,1))[0U]));

brl.mod/blitz.mod/blitz_enum.c defines the bbEnumValues() function this way:

BBArray * bbEnumValues(BBEnum * bbEnum) {
    BBArray * values = &bbEmptyArray;

    int size = 4;
    char t = bbEnum->type[0];
    switch( t ) {
        case 'b':size=1;break;
        case 's':size=2;break;
        case 'l':size=8;break;
        case 'y':size=8;break;
        case 'z':size=sizeof(BBSIZET);break;
    }

    values = bbArrayNew1DStruct(bbEnum->atype, bbEnum->length, size, 0);

    char * p = BBARRAYDATA(values, 0);

    memcpy(p, bbEnum->values, size * bbEnum->length);

    return values;
}

Now my questions: while this not a biggy (dunno who would call it the way I do in my sample) I thought enums are kind of "constant" - so the returned "Values()"-array could be created right during compilation already - or not?

Is this not done to save memory (only create if needed) or are enums not really constant? Is this to ensure that (the returned) arrays are not manipulated for future calls to it?

HurryStarfish commented 4 years ago

Since arrays are mutable and nothing is stopping you from doing ETest.Values()[0] = 123, you'd be able to break the array for future .Value() calls. To prevent that, it needs to create a new array.

My suggestion is that once generics support is more complete, .Value() could be changed to return an IIterable instead. Then it will no longer be necessary to create copies of the backing array, as long as you only want to read/iterate the values. Until then you could store the array in a Global somewhere if the performance worries you.