Oxygen Basic
Information => Development => Topic started by: Brian Alvarez on May 30, 2019, 10:01:29 AM
-
Charles, how tested is recursiveness with functions? I am experiencing some issues and i am clueless right now.
-
Well tested. O2 is packed with recursions, but It makes debugging a real challenge. You need to be able to monitor your recursion route, especially with indirect recursions.
-
This code:
FUNCTION RECURSIVE(BYVAL INT LVL) AS LONG
IF LVL > 5 THEN
RETURN 0
END IF
INT I = 0
REDIM STRING LS(5)
FOR I = 1 TO 5
LS[I] = "LEVEL " + str(LVL) + " STRING"
NEXT I
print space(LVL*5) " before going deeper: " + LS[1] chr(13, 10)
RECURSIVE(LVL+1)
print space(LVL*5) " after going deeper: " + LS[1] chr(13, 10)
END FUNCTION
RECURSIVE(0)
Outputs this:
before going deeper: LEVEL 0 STRING
before going deeper: LEVEL 1 STRING
before going deeper: LEVEL 2 STRING
before going deeper: LEVEL 3 STRING
before going deeper: LEVEL 4 STRING
before going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
after going deeper: LEVEL 5 STRING
After going deeper, all strings are overwritten....
-
STRING LS[5]
and
DIM STRING LS(5)
Both work fine, but you have to know how many strings to allocate, because only literals are alllowed...
In my program i do this:
LONG NELEMS = PARSECOUNT(O, 0, ";")-1
REDIM STRING LS(NELEMS)
Allocating space for hundreds of lines (to be safe) when only one is required is not very efficient... what can i do when speed is crucial?
-
Hi Brian,
redim currently creates static arrays (when inside a function), but I think it would be generally safe to remove the static constraint.
#ifndef %2_buffer
dim static string %2_buffer = ""
dim static %1 byref %2
#endif
This is the core redim macro. You can override it:
def redim
#ifndef %2_buffer
dim static string %2_buffer = ""
dim static %1 byref %2
#endif
scope
int _qb_ = %3
int _le_ = len %2_buffer
int _qn_ = _le_ / sizeof(%1)
#if match "%4","clear"
int _i_
for _i_=1 to _qn_
#if typecodeof(%2)>=0x200
#ifdef %1.destructor
%2[_i_].destructor
#endif
#elseif typecodeof(%2)>=0xa0
%2[_i_]=""
#else
%2[_i_]=0
#endif
next
#endif
#if typecodeof(%2)>=0xa0
if _qb_<_qn_
_qb_=_qn_ 'disallow reduction
endif
#endif
if _qb_ > _qn_
%2_buffer += nuls( sizeof(%1) * (_qb_ - _qn_))
elseif _qb_ < _qn_
%2_buffer = left( %2_buffer, sizeof(%1) * _qb_ )
endif
@%2=strptr(%2_buffer)
end scope
end def
-
Ok, thanks Charles!
Is it safe if i (instead of overriding it) make a copy of it with.. lets say... the name "redim2" with the static removed?
I use REDIM in other areas of the program and i dont want to disrupt their actual behaviour.
-
It is indeed well tested. And pretty fast! I can make 10000 recursions to my complex function in 0.2 seconds.... not bad!!! :D
-
If a variable is first redimed in global space, it will always be 'static' anyway. Are there any instances where you need an implicitly static redim?
There is the issue of using static variables in threadable functions.
Also, do any of your classes use redim?
-
Hello Charles, No... not anymore. None of them use DIM or REDIM anymore. For the moment i used a clever alternative that i hope you can see soon.
The recursive feature was for improving the JSON features. Now any UDT can be used for working with JSON. Yeah!
Plus i added a new datatype... JSON. It works pretty nice! I hope the world can see it soon. :) It can parse any JSON string and allow the compiler to
use it in an Object-oriented way. No need to declare its nodes!
LOCAL J AS JSON = "{""somestring"" : ""THIS IS THE DATA CONTAINED HERE""}"
STDOUT J.somestring
;D
Added:
The data source for JSON variables does not need to be a string literal, obviously. The engine does not parse literal strings to "guess" its members.
The data source can be a string, or something downloaded from internet. Everything is procesed at run time, not compilation time.
-
By the way... what is the issue with STATIC and THREADABLE functions?
-
Functions which may be accessed by more than one thread at the same time, generally need to avoid using static variables. They will produce the same over-writing conflicts that you found with recursion.
PS: JSON is new to me. I will have to study further.
-
Well... how about converting STATIC variables into THREADED variables when declared nside a THREADED function?
I already implemented them, so, it should be no problem.
-
Charles, if you want, you can implement threaded variables fairly easy, take a look at:
- TlsAlloc()
- TlsFree()
- TlsSetValue()
Basically all you need to do is have TLS pointer and a Global array, each thread will point to a different slot in the global array. Here's how i did it, this class works for string and wstring:
MACRO ¤TYPE_STR_TRV(dtype)
¤TRV_NAME_DEF(dtype)
dim ss(200) as dtype
int siz = 0
sys adr = 0
int ntm = 0
int ta = 0
int gix = 0
method constructor(int sv, av, nt)
siz = sv
adr = av
ntm = nt
ta = ¤TlsAlloc()
end method
method destructor()
int i
for i = 1 to 200
ss[i] = ""
next i
¤TlsFree(this.ta)
end method
method alloc() as int
this.gix += 1
' to do: redim ss if necessary!
¤TlsSetValue(this.ta, this.gix)
ss[this.gix] = ""
return this.gix
end method
function w(dtype v)
int ix = ¤TlsGetValue(this.ta)
if (ix=0) then ix = this.alloc()
ss[ix] = v
end function
function r() as dtype
int ix = ¤TlsGetValue(this.ta)
if (ix=0) then ix = this.alloc()
return ss[ix]
end function
function p() as sys
int ix = ¤TlsGetValue(this.ta)
if (ix=0) then ix = this.alloc()
return @ss[ix]
end function
end class
END MACRO
This is an old version that still uses DIM, but you can use any method of storing strings. I currently use getmemory(), but that class is more complex and is not as clear of an example of the TLS functions. This old one is clearer.
:)
-
Plus i added a new datatype... JSON. It works pretty nice! I hope the world can see it soon. It can parse any JSON string and allow the compiler to
use it in an Object-oriented way. No need to declare its nodes!
I have been using the MySQL server as my JSON parsing engine. The project is mirroring a remote DB which I convert from JSON data to standard table schemas.
-
John, can you show me an example of what you do with JSON? I would like to see if im covering all the needs with it.
-
I'll send the library as an attachment in an e-mail to you. It's code I wrote for a client.