Author Topic: Problem with parameter overflow in class method  (Read 357 times)

0 Members and 1 Guest are viewing this topic.

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Problem with parameter overflow in class method
« on: December 27, 2018, 03:14:48 AM »
 Hello Charles, I suspect this one is going to be a headache, sorry... :(

 I am converting this code:

Code: [Select]
#COMPILE EXE
#COMPILER OXYGEN
#OPTIONS X64
#DIM ALL

GLOBAL RK() AS LONG

FUNCTION PBMAIN() AS LONG

DIM RK(10)

RK(1) = 22

PRINTBR STR$(RK(1))

END FUNCTION

This is the generated code, everything looks fine.

Code: [Select]
'Generated with PluriBASIC 6.0.123201.0

$ filename "C:\Users\Diamante\Documents\PluriBASIC\projects\pluridll\overflow.exe"

uses rtl64

#def __dim1 (d1-bnd[1])
#def __dim2 (d2-bnd[3])
#def __dim3 (d3-bnd[5])
#def __class_name_define class _arr_%1
Declare Function PluriBASICMessageBox  Lib "user32.dll" Alias "MessageBoxA"

' STARTS PLURIBASIC_PREPARE.BIN
' This code is executed before anything else, if you want to do something after defining other things, see PLURIBASIC_INIT


' END OF PLURIBASIC_PREPARE.BIN
' STARTS ARRAY_DIM.BIN

macro __declare_array_ndtt(dtype)
    __class_name_define(dtype)
   
        public dtype t ' for use with typeof on this array.
        int dims       ' Number of dimensions
        int elems      ' Number of elements.
        int elemsize   ' Number of elements.
        int slength    ' length of strings.
        int ispointer  ' is pointer flag.
        sys hBuffer    ' Address of the buffer
        sys hCustAddr  ' Address provided by the inline code.
        int BuffLen    ' length of the buffer in bytes
        string dtType  ' Data type for the array.
        int iType      ' Data type ID for the array.
        int elemsize   ' Data type size.
        int dimensioned' -1 if dimensioned.
        int Head       ' size of the array header 
        int bnd[10]    ' bounds.
     
        function redim(int pr, int * d, n)
            int i
            dimensioned = -1
            int ne = 1
            for i = 1 to n step 2
                bnd[i+0] = d[i+0]
                bnd[i+1] = d[i+1]
                ne       *= ((d[i+1]+1)-d[i+0])
            next
            if ne < elems then
                if dtType = "STR" then
                    if hBuffer then
                        dtype dt at (hBuffer + head)
                        for i = ne+1 to elems
                            frees dt(i)
                        next
                    end if     
                end if
            end if       
            elems = ne
            int nBufLen
            nBufLen = (elems * sizeof(sys)) + head + 32
            sys nBuffer = getmemory(nBufLen)
            int eBfCopy = BuffLen
            if BuffLen
              if BuffLen>nBufLen then
                  eBfCopy = nBufLen
              end if
              copy nBuffer, hBuffer, eBfCopy
              freememory hBuffer
            endif
            hBuffer = nBuffer
            BuffLen = nBufLen       
        end function 
     
        method constructor(int * d, n, isptr, slen, string dtyp, int dtID, int dtSize, sys hAddr)
            head      = 0
            ispointer = isptr
            dtType    = dtyp
            slength   = slen
            hCustAddr = hAddr
            iType     = dtID
            elemsize  = dtSize
            dims = n / 2
            if n > -1 then
                this.redim(0, d, n)
            end if       
        end method
       
        function destructor()
            int i
            if (dtType = "STR") then
                dtype dt at (hBuffer + head)
                for i = 0 to elems
                    frees dt(i)
                next
            end if   
            freememory(hBuffer)
            hBuffer = 0
            BuffLen = 0
        end function
       
        function b() as string
            return ""
        end function   

         '======================================================================
        function c(int d1, dtype v)
            dtype dt at (hBuffer + head)           
        print "setting"
            dt(__dim1) = v
        end function
       
        function c(int d1) as dtype
            dtype dt at (hBuffer + head)
        print "getting"           
            return dt(__dim1)
        end function

         function c(int d1, d2, dtype v)
            dtype dt at (hBuffer + head)
            dt(__dim1 * __dim2) = v
        end function

         function c(int d1, d2) as dtype
            dtype dt at (hBuffer + head)                       
            return dt(__dim1 * __dim2)
        end function

         function c(int d1, d2, d3, dtype v)
            dtype dt at (hBuffer + head)
            dt(__dim1 * __dim2 + __dim3) = v
        end function

         function c(int d1, d2, d3) as dtype
            dtype dt at (hBuffer + head)
            return dt(__dim1 * __dim2 + __dim3)
        end function
        '======================================================================
        function p(int d1) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1)
        end function
       
        function p(int d1, d2) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1 * __dim2)
        end function

         function p(int d1, d2, d3) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1 * __dim2 + __dim3)
        end function   
        '======================================================================
        function strptr(int d1) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1
            return strptr(dt(i))
        end function
       
        function strptr(int d1, d2) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1 * __dim2
            return strptr(dt(i))
        end function
       
        function strptr(int d1, d2, d3) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1 * __dim2 + __dim3
            return strptr(dt(i))
        end function
        '======================================================================
         
        function lbound(int d) as int
          return bnd[d]
        end function
       
        function ubound(int d) as int
          return bnd[d+1]
        end function
       
        function arrayattr(int d) as int
          // not yet implemented.       
          if d = 0 then return dimensioned
          if d = 1 then return iType   
          if d = 2 then return ispointer   
          if d = 3 then return dims         
          if d = 4 then return elems         
          if d = 5 then return elemsize
          return 0
        end function 
    end class
end macro
' END OF ARRAY_DIM.BIN
' STARTS STR$.BIN
' STARTS LTRIM$.BIN
// returns a trimed string
FUNCTION LTRIM(string src, long a = 0, string ch = " ") as string

    if len(src) = 0 then return ""
    if len(ch) = 0 then return ""
   
    byte srcchar at strptr(src)
    byte trichar at strptr(ch)
    long p1 = 1
    long index   
    long cha   
       
    if a then
        for index = 1 to len(src)       
            for cha = 1 to len(ch)       
                if srcchar[index] = trichar[cha] then
                    goto checknextchar                     
                end if
            next
            p1 = index
            exit for
            checknextchar:
        next
        return mid(src, p1)
    else       
        for index = 1 to len(src)
            for cha = 1 to len(ch)       
                if srcchar[index+cha-1] <> trichar[cha] then
                    goto nomorematches
                end if               
            next
            p1 += len(ch)             
        next
        nomorematches:       
        return mid(src, p1)
    end if
   
END FUNCTION
' END OF LTRIM$.BIN
' CONTINUES (1) STR$.BIN
' Enter the stock code and functions here.
FUNCTION _STR(double v, long d = 8) as string
    long d2 = d-1
    if v < 0 then
        return str(v, d2)
    else
        string ss = str(v, d2)
        if instr(ss, ".") then
            return " " & LTRIM(ss, 0, "0")
        else
            return " " & ltrim(ss)
        end if
    end if
END FUNCTION


' END OF STR$.BIN
' STARTS PRINTR.BIN
' STARTS MSGBOX.BIN
FUNCTION MSGBOX(string sText, sys mOptions = 0, string sCaption = "PluriBASIC") AS LONG
   FUNCTION = PluriBASICMessageBox(0, sText, sCaption, mOptions)
END FUNCTION
' END OF MSGBOX.BIN
' CONTINUES (1) PRINTR.BIN
macro PRINTR(p1, p2)
    MSGBOX(p1 + p2)
end macro
' END OF PRINTR.BIN
' STARTS PLURIBASIC_INIT.BIN
' This code is executed before anything else, if you want to do something before nything else, see PLURIBASIC_PREPARE
       
   
   
   

' END OF PLURIBASIC_INIT.BIN
' STARTS CALLBACKDATA.BIN
' END OF CALLBACKDATA.BIN

' SYSTEM DECLARES FOR ARRAYS

  __declare_array_ndtt(long)

DECLARE FUNCTION PBMAIN() AS LONG
new _arr_long rk(int{0, 0}, -1, 0, 0, "LNG", 5, 4, 0)


' Initializes various things in the script.
FUNCTION PluriBASIC_Initialize() AS LONG

END FUNCTION

FUNCTION PBMAIN() AS INT
   INT _05FUNCTION = 0
   rk.redim(0, int{0, 10}, countof)
   rk.c(1) = 22
   PRINTR(_STR(rk.c(1)), "</br>")
END FUNCTION

PBMAIN() ' invoke entry point

 I set a message box that should be displayed at RK(1) = 22, but it gets never fired and the value is never stored in the class. The application does not crash, but it doesnt work as it should.

 Please take a look when you can? This is holding me back from more advanced stuff. :(

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Re: Problem with parameter overflow in class method
« Reply #1 on: December 27, 2018, 03:21:10 AM »
More info... notice how it works perfectly fine if i generate a STRING array:

Code: [Select]
#COMPILE EXE
#COMPILER OXYGEN
#OPTIONS X64
#DIM ALL

GLOBAL RK() as STRING

FUNCTION PBMAIN() AS LONG

DIM RK(10)

RK(1) = "22"

PRINTBR RK(1)

END FUNCTION

Generated code:

Code: [Select]
'Generated with PluriBASIC 6.0.123201.0

$ filename "C:\Users\Diamante\Documents\PluriBASIC\projects\pluridll\overflow.exe"

uses rtl64

#def __dim1 (d1-bnd[1])
#def __dim2 (d2-bnd[3])
#def __dim3 (d3-bnd[5])
#def __class_name_define class _arr_%1
Declare Function PluriBASICMessageBox  Lib "user32.dll" Alias "MessageBoxA"

' STARTS PLURIBASIC_PREPARE.BIN
' This code is executed before anything else, if you want to do something after defining other things, see PLURIBASIC_INIT


' END OF PLURIBASIC_PREPARE.BIN
' STARTS ARRAY_DIM.BIN

macro __declare_array_ndtt(dtype)
    __class_name_define(dtype)
   
        public dtype t ' for use with typeof on this array.
        int dims       ' Number of dimensions
        int elems      ' Number of elements.
        int elemsize   ' Number of elements.
        int slength    ' length of strings.
        int ispointer  ' is pointer flag.
        sys hBuffer    ' Address of the buffer
        sys hCustAddr  ' Address provided by the inline code.
        int BuffLen    ' length of the buffer in bytes
        string dtType  ' Data type for the array.
        int iType      ' Data type ID for the array.
        int elemsize   ' Data type size.
        int dimensioned' -1 if dimensioned.
        int Head       ' size of the array header 
        int bnd[10]    ' bounds.
     
        function redim(int pr, int * d, n)
            int i
            dimensioned = -1
            int ne = 1
            for i = 1 to n step 2
                bnd[i+0] = d[i+0]
                bnd[i+1] = d[i+1]
                ne       *= ((d[i+1]+1)-d[i+0])
            next
            if ne < elems then
                if dtType = "STR" then
                    if hBuffer then
                        dtype dt at (hBuffer + head)
                        for i = ne+1 to elems
                            frees dt(i)
                        next
                    end if     
                end if
            end if       
            elems = ne
            int nBufLen
            nBufLen = (elems * sizeof(sys)) + head + 32
            sys nBuffer = getmemory(nBufLen)
            int eBfCopy = BuffLen
            if BuffLen
              if BuffLen>nBufLen then
                  eBfCopy = nBufLen
              end if
              copy nBuffer, hBuffer, eBfCopy
              freememory hBuffer
            endif
            hBuffer = nBuffer
            BuffLen = nBufLen       
        end function 
     
        method constructor(int * d, n, isptr, slen, string dtyp, int dtID, int dtSize, sys hAddr)
            head      = 0
            ispointer = isptr
            dtType    = dtyp
            slength   = slen
            hCustAddr = hAddr
            iType     = dtID
            elemsize  = dtSize
            dims = n / 2
            if n > -1 then
                this.redim(0, d, n)
            end if       
        end method
       
        function destructor()
            int i
            if (dtType = "STR") then
                dtype dt at (hBuffer + head)
                for i = 0 to elems
                    frees dt(i)
                next
            end if   
            freememory(hBuffer)
            hBuffer = 0
            BuffLen = 0
        end function
       
        function b() as string
            return ""
        end function   

         '======================================================================
        function c(int d1, dtype v)
            dtype dt at (hBuffer + head)           
        print "setting"
            dt(__dim1) = v
        end function
       
        function c(int d1) as dtype
            dtype dt at (hBuffer + head)
        print "getting"           
            return dt(__dim1)
        end function

         function c(int d1, d2, dtype v)
            dtype dt at (hBuffer + head)
            dt(__dim1 * __dim2) = v
        end function

         function c(int d1, d2) as dtype
            dtype dt at (hBuffer + head)                       
            return dt(__dim1 * __dim2)
        end function

         function c(int d1, d2, d3, dtype v)
            dtype dt at (hBuffer + head)
            dt(__dim1 * __dim2 + __dim3) = v
        end function

         function c(int d1, d2, d3) as dtype
            dtype dt at (hBuffer + head)
            return dt(__dim1 * __dim2 + __dim3)
        end function
        '======================================================================
        function p(int d1) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1)
        end function
       
        function p(int d1, d2) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1 * __dim2)
        end function

         function p(int d1, d2, d3) as dtype*
            dtype dt at (hBuffer + head)
            return @dt(__dim1 * __dim2 + __dim3)
        end function   
        '======================================================================
        function strptr(int d1) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1
            return strptr(dt(i))
        end function
       
        function strptr(int d1, d2) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1 * __dim2
            return strptr(dt(i))
        end function
       
        function strptr(int d1, d2, d3) as sys   
            dtype dt at (hBuffer + head)
            int i = __dim1 * __dim2 + __dim3
            return strptr(dt(i))
        end function
        '======================================================================
         
        function lbound(int d) as int
          return bnd[d]
        end function
       
        function ubound(int d) as int
          return bnd[d+1]
        end function
       
        function arrayattr(int d) as int
          // not yet implemented.       
          if d = 0 then return dimensioned
          if d = 1 then return iType   
          if d = 2 then return ispointer   
          if d = 3 then return dims         
          if d = 4 then return elems         
          if d = 5 then return elemsize
          return 0
        end function 
    end class
end macro
' END OF ARRAY_DIM.BIN
' STARTS PRINTR.BIN
' STARTS MSGBOX.BIN
FUNCTION MSGBOX(string sText, sys mOptions = 0, string sCaption = "PluriBASIC") AS LONG
   FUNCTION = PluriBASICMessageBox(0, sText, sCaption, mOptions)
END FUNCTION
' END OF MSGBOX.BIN
' CONTINUES (1) PRINTR.BIN
macro PRINTR(p1, p2)
    MSGBOX(p1 + p2)
end macro
' END OF PRINTR.BIN
' STARTS PLURIBASIC_INIT.BIN
' This code is executed before anything else, if you want to do something before nything else, see PLURIBASIC_PREPARE
       
   
   
   

' END OF PLURIBASIC_INIT.BIN
' STARTS CALLBACKDATA.BIN
' END OF CALLBACKDATA.BIN

' SYSTEM DECLARES FOR ARRAYS

  __declare_array_ndtt(bstring)

DECLARE FUNCTION PBMAIN() AS LONG
new _arr_bstring rk(int{0, 0}, -1, 0, 0, "STR", 23, 4, 0)


' Initializes various things in the script.
FUNCTION PluriBASIC_Initialize() AS LONG

END FUNCTION

FUNCTION PBMAIN() AS INT
   INT _05FUNCTION = 0
   rk.redim(0, int{0, 10}, countof)
   rk.c(1) = "22"
   PRINTR(rk.c(1), "</br>")
END FUNCTION

PBMAIN() ' invoke entry point

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Re: Problem with parameter overflow in class method
« Reply #2 on: December 27, 2018, 03:43:49 AM »
Extra note... it also works with DOUBLE, but fails with SINGLE and all other integer datatypes i tested with, like INTEGER, BYTE, QUAD, etc.

So, the error must be related to STRING and DOUBLE vs all other datatypes.

BTW, it also works fine with UDT's (a different but similar class is generated for UDT's).

Note:
To test with DOUBLE and SINGLE, just change the line:

Code: [Select]
__declare_array_ndtt(bstring)
to:

Code: [Select]
__declare_array_ndtt(double)
or:

Code: [Select]
__declare_array_ndtt(single)
and the code that creates the class, for example:

Code: [Select]
new _arr_double rk(int{0, 0}, -1, 0, 0, "DOUBLE", 7, 8, 0)
As well as the lines that assign or retrieve the values. For example:

Code: [Select]
rk.c(1) = 22.555

Charles Pegge

  • Admin Support Member
  • *****
  • Posts: 3974
    • Oxygen Basic
Re: Problem with parameter overflow in class method
« Reply #3 on: December 28, 2018, 08:03:41 AM »
Brian,

There is no inherent difference between double/string and the other primitives. (possibly slots on the stack when passing params in 32-bit mode).

I'm thinking about ways to avoid generating separate classes for each array type...

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Re: Problem with parameter overflow in class method
« Reply #4 on: December 28, 2018, 02:43:15 PM »
 Hello Charles, at this point i dont think i would change it to another method, at least not for now. This array system i have works pretty good (besides this glitch), and it is very fast, and it has been wired together for varptr, strpr, arrayattr, pre declaring arrays, all data types, has been done to work with INCR, DECR, can be passed byval or byref, can be used in complex statements... Etc... etc... etc... it would take long to switch to other method at this point.

 Besides, i think the overflow thing will have to be fixed at some point, so, maybe i will just try to slightly change what i have now. Probably avoiding parameter overflow for now.

 Also nothice that the same class should work for most datatypes (in theory), so, i am not creating many classes (at least not manually, but internally the compiler  has to do it).

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Re: Problem with parameter overflow in class method
« Reply #5 on: January 04, 2019, 04:43:13 AM »
 Hello Charles, after some consideration, i came to the conclusion that, if you implement a new way to do multi-dimensions,
i am willing to give it a try. There are a lot of things that would need to be changed, but i would like to take a look. :)

Brian Alvarez

  • Full Member
  • ***
  • Posts: 231
    • PluriBASIC
Re: Problem with parameter overflow in class method
« Reply #6 on: January 12, 2019, 08:59:07 PM »
Charles, i figured it out. I know why the parameter overflow is not working as expected.

I have the following 4 functions in my class:

Code: [Select]
        function c(int d1, dtype v)
            PRINT "1"
            dtype dt at hBuffer
            dt(_32d1) = v
        end function
       
        function c(int d1) as dtype
            PRINT "2"
            dtype dt at hBuffer               
            return dt(_32d1)
        end function

        function c(int d1, d2, dtype v)
             PRINT "3"
            dtype dt at hBuffer
            dt(_32d1 * _32d2) = v
        end function

        function c(int d1, int d2) as dtype
            PRINT "4"         
            dtype dt at hBuffer                       
            return dt(_32d1 * _32d2)
        end function

Then i invoke this code:

Code: [Select]
   dnumbs.c(0) = 37
   print dnumbs.c(0)

 Then i see 2 message boxes, as expected, but the numbers i expect are "1" and then "2". However, i see "4" and then "2".
It seems like oxygen is matching this:

Code: [Select]
dnumbs.c(0) = 37
 With:

Code: [Select]
function c(int d1, int d2) as dtype
 I understand why... it is taking 0 and 37 as "int,int".  That explains why it works with double, but fails with int, the matching engine distinguishes better when the value is not int (in this case dtype is a macro paramter that equals int).

 Would it be too difficult to make it match the "setter" instead of the "getter" when there is a "="?