strange malfunction with udt

General discussion for topics related to the FreeBASIC project or its community.
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: strange malfunction with udt

Post by fxm »

Another example of "regression" with fbc 1.10.0 when evaluating 'u <> v' ('u' being a TU instance and 'v' a TV instance), with conversion possible via a String for example:

Code: Select all

#define TU_ctor_from_TV               '' A
#define TU_ctor_from_string           '' B
#define TV_cast_to_TU                 '' C
#define TV_cast_to_string             '' D
#define op_inequal_from_TU_from_TU    '' E
#define op_inequal_from_TU_from_TV    '' F

'' fbc version   1.09.0   1.10.0
''  Priority 1      F        F
''  Priority 2     C+E      C+E
''  Priority 3     A+E      A+E
''  Priority 4    D+B+E

Type _TV As TV

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_string
        Declare Constructor(Byref s As String)
    #endif
    Declare Destructor()
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_TU
        Declare Operator Cast() Byref As TU
    #endif
    #ifdef TV_cast_to_string
        Declare Operator Cast() As string
    #endif
End Type

Dim Shared As TU u
Dim Shared As TV v

Constructor TU()
    If @This <> @u Then
        Print "    Constructor UDT()"
    End If
End Constructor

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "    Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_string
    Constructor TU(Byref s As string)
        Print "    Constructor TU(Byref As string)"
    End Constructor
#endif

Destructor TU()
    If @This <> @u Then
        Print "  Destructor TU()"
    End If
End Destructor

#ifdef TV_cast_to_TU
    Operator TV.Cast() Byref As TU
        Print "    Operator TV.Cast() Byref As TU"
        Return u
    End Operator
#endif

#ifdef TV_cast_to_string
    Operator TV.Cast() As string
        Print "    Operator TV.Cast() Byref As String"
        Return ""
    End Operator
#endif

#ifdef op_inequal_from_TU_from_TU
    Operator <>(Byref ul As TU, Byref ur As TU) As Integer
        Print "    Operator <>(Byref As TU, Byref As TU) As Integer"  
        Return 0
    End Operator
#endif

#ifdef op_inequal_from_TU_from_TV
    Operator <>(Byref ul As TU, Byref vr As TV) As Integer
        Print "    Operator <>(Byref As TU, Byref As TV) As Integer"  
        Return 0
    End Operator
#endif

Print "'u <> v':"
If u <> v Then End If

Sleep

The priority 4 with fbc 1.09.0:

Code: Select all

Priority 4:
    Operator TV.Cast() Byref As String
    Constructor TU(Byref As string)
    Operator <>(Byref As TU, Byref As TU) As Integer
  Destructor TU()
disappeared with fbc 1.10.0.
coderJeff
Site Admin
Posts: 4323
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: strange malfunction with udt

Post by coderJeff »

I have studied this for a couple of days and I have a fix. It is not what I expected so there is probably a little bit more here to understand. But I am going to push the changes soon anyway. It's a one line change that should give the same behaviour as fbc 1.09.0 for this context. And I have added the most recent tests from this topic. thank-you fxm for the code to build the "regression" tests.

For the comparison operator (actually, any binary operator, I think), at least one parameter of the two should (needs to?) match the UDT type to start with. But constructors and casts are allowed to help give a matching argument to the binary operator call. It looks like the intent is that we don't want to allow multiple constructors or casts to be chained together - at most one of each. A single constructor and/or cast to get the needed arguments to make the comparison. I know, that description is lacking and shows that I still do not have the full understanding of what currently exists in compiler logic.

Regardless of my lack of understanding, best and most efficient code generation will result when the comparison operator (or any binary operator I think) is explicitly defined. Invoking constructors and/or casts result in allocation of temporary instances and variables. For the comparison operator which should be access only (i.e. read-only), ideally an exact matching comparison operator is declared and defined by the user to avoid any temporary allocations thus improving the size and speed of the end program.
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: strange malfunction with udt

Post by fxm »

My last regression test above for the '<>' operator is actually done so that it can easily fit into my previous full test program:

Code: Select all

'' This code allows to check the precedence of the constructors/operators (among the eleven)
''    for each conversion/inheritance case (among the seventeen)
''    by commenting or not the #define lines only.

'' test cases selected:
#define dim_as_TU_from_TV
#define byval_as_TU_from_TV
#define byref_as_TU_from_TV
#define equal_as_TU_from_TV
#define function_equal_from_TV_to_TU
#define return_from_TV_to_TU
#define inequal_from_TU_from_TV
#define dim_as_TW_from_TW
#define byval_as_TW_from_TW
#define equal_as_TW_from_TW
#define function_equal_from_TW_to_TW
#define return_from_TW_to_TW
#define dim_as_TU_from_TW
#define byval_as_TU_from_TW
#define equal_as_TU_from_TW
#define function_equal_from_TW_to_TU
#define return_from_TW_to_TU

'' constructors/operators defined:
#define TU_ctor_from_TU
#define TU_ctor_from_TV
#define TU_ctor_from_TX
#define TU_let_from_TU
#define TU_let_from_TV
#define TU_let_from_TX
#define TU_dtor
#define TV_cast_to_TU
#define TV_cast_to_TX
#define op_inequal_from_TU_from_TU
#define op_inequal_from_TU_from_TV

'' TX type defined:
'#define TX_as_integer
'#define TX_as_integer_ptr
#define TX_as_string
'#define TX_as_UDT_with_integer
'#define TX_as_UDT_with_string

#ifdef TX_as_integer
    Type TX As Integer
#endif

#ifdef TX_as_integer_ptr
    Type TX As Integer Ptr
#endif

#ifdef TX_as_string
    Type TX As String
#endif

#ifdef TX_as_UDT_with_integer
    Type TX
        Dim As Integer I
    End Type
#endif

#ifdef TX_as_UDT_with_string
    Type TX
        Dim As String s
    End Type
#endif

Type _TV As TV

Type TU
    Dim As Integer I
    Declare Constructor()
    #ifdef TU_ctor_from_TU
        Declare Constructor(Byref u As TU)
    #endif
    #ifdef TU_ctor_from_TV
        Declare Constructor(Byref v As _TV)
    #endif
    #ifdef TU_ctor_from_TX
        Declare Constructor(Byref s As TX)
    #endif
    #ifdef TU_let_from_TU
        Declare Operator Let(Byref u As TU)
    #endif
    #ifdef TU_let_from_TV
        Declare Operator Let(Byref v As _TV)
    #endif
    #ifdef TU_let_from_TX
        Declare Operator Let(Byref s As TX)
    #endif
    #ifdef TU_dtor
        Declare Destructor()
    #endif
End Type

Type TV
    Dim As Integer I
    #ifdef TV_cast_to_TU
        Declare Operator Cast() Byref As TU
    #endif
    #ifdef TV_cast_to_TX
        Declare Operator Cast() Byref As TX
    #endif
End Type

Type TW Extends TU
End Type

Dim Shared As TX x0
Dim Shared As TU u0
Dim Shared As TV v0
Dim Shared As TW w0, w1

Constructor TU()
    If (@This <> @u0) And (@This <> @w0) And (@This <> @w1) Then
        Print "    Constructor TU()"
    End If
End Constructor

#ifdef TU_ctor_from_TU
    Constructor TU(Byref u As TU)
        Print "    Constructor TU(Byref As TU)"
    End Constructor
#endif

#ifdef TU_ctor_from_TV
    Constructor TU(Byref v As TV)
        Print "    Constructor TU(Byref As TV)"
    End Constructor
#endif

#ifdef TU_ctor_from_TX
    Constructor TU(Byref s As TX)
        Print "    Constructor TU(Byref As TX)"
    End Constructor
#endif

#ifdef TU_let_from_TU
    Operator TU.Let(Byref u As TU)
        Print "    Operator TU.Let(Byref As TU)"
    End Operator
#endif

#ifdef TU_let_from_TV
    Operator TU.Let(Byref v As TV)
        Print "    Operator TU.Let(Byref As TV)"
    End Operator
#endif

#ifdef TU_let_from_TX
    Operator TU.Let(Byref s As TX)
        Print "    Operator TU.Let(Byref As TX)"
    End Operator
#endif

#ifdef TU_dtor
    Destructor TU()
        If (@This <> @u0) And (@This <> @w0) And (@This <> @w1) Then
            Print "  Destructor TU()"
        End If
    End Destructor
#endif

#ifdef TV_cast_to_TU
    Operator TV.Cast() Byref As TU
        Print "    Operator TV.Cast() Byref As TU"
        Return u0
    End Operator
#endif

#ifdef TV_cast_to_TX
    Operator TV.Cast() Byref As TX
        Print "    Operator TV.Cast() Byref As TX"
        Return x0
    End Operator
#endif

#ifdef op_inequal_from_TU_from_TU
    Operator <>(Byref ul As TU, Byref ur As TU) As Integer
        Print "    Operator <>(Byref As TU, Byref As TU) As Integer"  
        Return 0
    End Operator
#endif

#ifdef op_inequal_from_TU_from_TV
    Operator <>(Byref ul As TU, Byref vr As TV) As Integer
        Print "    Operator <>(Byref As TU, Byref As TV) As Integer"  
        Return 0
    End Operator
#endif

#ifdef byval_as_TU_from_TV
    Sub s1(Byval u As TU)
    End Sub
#endif

#ifdef byref_as_TU_from_TV
    Sub s2(Byref u As TU)
    End Sub
#endif

#ifdef function_equal_from_TV_to_TU
    Function f11() As TU
        Function = v0
    End function
#endif

#ifdef return_from_TV_to_TU
    Function f12() As TU
        Return v0
    End function
#endif

#ifdef byval_as_TW_from_TW
    Sub s21(Byval w As TW)
    End Sub
#endif

#ifdef function_equal_from_TW_to_TW
    Function f21() As TW
        Function = w0
    End function
#endif

#ifdef return_from_TW_to_TW
    Function f22() As TW
        Return w0
    End function
#endif

#ifdef byval_as_TU_from_TW
    Sub s31(Byval u As TU)
    End Sub
#endif

#ifdef function_equal_from_TW_to_TU
    Function f31() As TU
        Function = w0
    End function
#endif

#ifdef return_from_TW_to_TU
    Function f32() As TU
        Return w0
    End function
#endif

Print "-------------------- Conversion (v -> u) ---------------------"
Print

#ifdef dim_as_TU_from_TV
    Scope
        Print "'Dim As TU u = v':"
        Dim As TU u = v0
    End Scope
    Print
#endif

#ifdef byval_as_TU_from_TV
    Scope
        Print "'Byval As TU' (from TV):"
        s1(v0)
    End Scope
    Print
#endif

#ifdef byref_as_TU_from_TV
    Scope
        Print "'Byref As TU' (from TV):"
        s2(v0)
    End Scope
    Print
#endif

#ifdef equal_as_TU_from_TV
    Scope
        Print "'u = v':"
        u0 = v0
    End Scope
    Print
#endif

#ifdef function_equal_from_TV_to_TU
    Scope
        Print "'Function = v' to TU:"
        f11()
    End Scope
    Print
#endif

#ifdef return_from_TV_to_TU
    Scope
        Print "'Return v' to TU:"
        f12()
    End Scope
    Print
#endif

#ifdef inequal_from_TU_from_TV
    Scope
        Print "'u <> v':"
        If u0 <> v0 Then End If
    End Scope
    Print
#endif

Print "------------------- Inheritance (TU <- TW) -------------------"
Print

#ifdef dim_as_TW_from_TW
    Scope
        Print "'Dim As TW w = w0':"
        Dim As TW w = w0
    End Scope
    Print
#endif

#ifdef byval_as_TW_from_TW
    Scope
        Print "'Byval As TW' (from TW):"
        s21(w0)
    End Scope
    Print
#endif

#ifdef equal_as_TW_from_TW
    Scope
        Print "'w = w0':"
        w1 = w0
    End Scope
    Print
#endif

#ifdef function_equal_from_TW_to_TW
    Scope
        Print "'Function = w' to TW:"
        f21()
    End Scope
    Print
#endif

#ifdef return_from_TW_to_TW
    Scope
        Print "'Return w' to TW:"
        f22()
    End Scope
    Print
#endif

Print "----- Conversion with Inheritance (w -> u with TU <- TW) -----"
Print

#ifdef dim_as_TU_from_TW
    Scope
        Print "'Dim As TU u = w':"
        Dim As TU u = w0
    End Scope
    Print
#endif

#ifdef byval_as_TU_from_TW
    Scope
        Print "'Byval As TU' (from TW):"
        s31(w0)
    End Scope
    Print
#endif

#ifdef equal_as_TU_from_TW
    Scope
        Print "'u = w':"
        u0 = w0
    End Scope
    Print
#endif

#ifdef function_equal_from_TW_to_TU
    Scope
        Print "'Function = w' to TU:"
        f31()
    End Scope
    Print
#endif

#ifdef return_from_TW_to_TU
    Scope
        Print "'Return w' to TU:"
        f32()
    End Scope
    Print
#endif

Sleep
I took the opportunity to add the visualization of the call to the TU_dtor.
fxm
Moderator
Posts: 12106
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: strange malfunction with udt

Post by fxm »

Regression now fixed by the fbc: internal: symbFind*() API commit.
(for more information, see viewtopic.php?p=296551#p296551)
Post Reply