Oxygen Basic
Programming => Bugs & Feature Requests => Topic started by: Brian Alvarez 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:
#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.
'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. :(
-
More info... notice how it works perfectly fine if i generate a STRING array:
#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:
'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
-
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:
__declare_array_ndtt(bstring)
to:
__declare_array_ndtt(double)
or:
__declare_array_ndtt(single)
and the code that creates the class, for example:
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:
rk.c(1) = 22.555
-
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...
-
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).
-
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. :)
-
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:
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:
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:
dnumbs.c(0) = 37
With:
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 "="?