bmx-ng / bcc

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

More struct issues. #537

Open GWRon opened 4 years ago

GWRon commented 4 years ago

Might be related to #532

SuperStrict
Framework Brl.StandardIO

Local k:TKeyWrapper = New TKeyWrapper

Type TKeyWrapper
    Field keyHoldInformation:SKeyHoldInformation[5]

    Field key100:SKeyHoldInformation

    Method New()
        For Local i:Int = 0 To 4
            Print "Init("+i+")"
            keyHoldInformation[i].Init(i)
            Print "    keyHoldInformation["+i+"].key = " + keyHoldInformation[i].key + "  id="+keyHoldInformation[i].id
        Next

        Print "Init(100)"
        key100.Init(100)
        Print "    key100.key = " + key100.key + "  id="+key100.id

    End Method
End Type

Struct SKeyHoldInformation
    Field key:Int
    Field id:Int
    Global _lastID:Int = 0

    Method New()
        _lastID :+ 1
        id = _lastID
    End Method

    Method Init(key:Int)
        Self.key = key
        Print "  called init with : " + key +"  self.key="+Self.key
    End Method
End Struct

Output:

Executing:untitled1.debug
Init(0)
  called init with : 0  self.key=0
    keyHoldInformation[0].key = 0  id=1
Init(1)
  called init with : 1  self.key=1
    keyHoldInformation[1].key = 0  id=2
Init(2)
  called init with : 2  self.key=2
    keyHoldInformation[2].key = 0  id=3
Init(3)
  called init with : 3  self.key=3
    keyHoldInformation[3].key = 0  id=4
Init(4)
  called init with : 4  self.key=4
    keyHoldInformation[4].key = 0  id=5
Init(100)
  called init with : 100  self.key=100
    key100.key = 100  id=6

As you can see, only the struct which is "not in the array" get's their key assigned. I assume all of them should get their keys assigned.

GWRon commented 4 years ago

If I replaced "struct" with "type" then everything works:

SuperStrict
Framework Brl.StandardIO

Local k:TKeyWrapper = New TKeyWrapper

Type TKeyWrapper
    Field keyHoldInformation:SKeyHoldInformation[5]

    Field key100:SKeyHoldInformation

    Method New()
        For Local i:Int = 0 To 4
            Print "Init("+i+")"
            keyHoldInformation[i] = New SKeyHoldInformation
            keyHoldInformation[i].Init(i)
            Print "    keyHoldInformation["+i+"].key = " + keyHoldInformation[i].key + "  id="+keyHoldInformation[i].id
        Next

        Print "Init(100)"
        key100 = New SKeyHoldInformation
        key100.Init(100)
        Print "    key100.key = " + key100.key + "  id="+key100.id

    End Method
End Type

Type SKeyHoldInformation
    Field key:Int
    Field id:Int
    Global _lastID:Int = 0

    Method New()
        _lastID :+ 1
        id = _lastID
    End Method

    Method Init(key:Int)
        Self.key = key
        Print "  called init with : " + key +"  self.key="+Self.key
    End Method
End Type

new output then:

Init(0)
  called init with : 0  self.key=0
    keyHoldInformation[0].key = 0  id=1
Init(1)
  called init with : 1  self.key=1
    keyHoldInformation[1].key = 1  id=2
Init(2)
  called init with : 2  self.key=2
    keyHoldInformation[2].key = 2  id=3
Init(3)
  called init with : 3  self.key=3
    keyHoldInformation[3].key = 3  id=4
Init(4)
  called init with : 4  self.key=4
    keyHoldInformation[4].key = 4  id=5
Init(100)
  called init with : 100  self.key=100
    key100.key = 100  id=6
GWRon commented 4 years ago

Generated C code for this piece of code:

keyHoldInformation[i].Init(100)

is:

struct _m_untitled1_SKeyHoldInformation bbt_=((struct _m_untitled1_SKeyHoldInformation*)BBARRAYDATA(o->__m_untitled1_tkeywrapper_keyholdinformation ,1))[((BBUINT)bbt_i)];

__m_untitled1_SKeyHoldInformation_Init_v_i((struct _m_untitled1_SKeyHoldInformation*)&bbt_,100);

So ... is this actually doing this:

shouldn't bbt_ be a pointer to the original data?

HurryStarfish commented 3 years ago

Not necessarily. It makes sense that you'd get a copy - that way it's consistent with what would happen if you replaced the array with a user-defined type that has an operator []. Think of [] and []= it as two different operators: keyHoldInformation[i] = New SKeyHoldInformation can actually modifies the array because indexed assignment ([]=) is a special operator (which is why you can overload it separately). But the regular [] index operator simply returns a value just like any regular method does, so you're calling .Init on a local copy. I wouldn't see this as a bug in the compiler, but it's something to be aware and careful with. One of the reasons why making structs mutable should be avoided when possible.