I can give you a small hint to find a few more information on some undocumented SDK-stuff.
Check the attachement, maybe it helps.
I am interested in developing a thinBasic module to implement as many Rexx builtin functions as possible. The goal is to simplify porting of Rexx scripts to thinBasic.
For example, a Rexx TRANSLATE function, with one operand, does what UCASE$ does, while a call to TRANSLATE(STR,NEW,OLD) is essentially what REPLACE$(STR,OLD,NEW) does. The net result is that porting of Rexx code is pretty hard, even though functionally thinBasic is quite comparable.
My current problem is that the documentation for creating a module is pretty limited. The thinBasic doc for the Module SDK is all blank.
Is there some "prototype" or sample module I could look at for an idea how to go about doing this? Is there documentation laying around that never got into the official docs?
Any help in this area would be appreciated.
Last edited by Robert Hodge; 12-06-2013 at 15:23.
I can give you a small hint to find a few more information on some undocumented SDK-stuff.
Check the attachement, maybe it helps.
I think there are missing some Forum-sections as beta-testing and support
Hi Quatras9,
the module developement is relatively simple and should allow you what you need.
First step
The sample ThinBasic module and header files are included in ThinBasic/SDK folder. There is a ZIP file you need to extract and it will give you module example in multiple languages.
Hint
Make sure you have examined the SDK sample, then the following will make more sense.
What do you need to implement your Translate function? I will give example in PowerBASIC, but it can be applied to other languages as well.
Your function in DLL could look like this:
Then you need to register the function to become visible for thinBASIC - this is done in LoadLibrary function of DLL:Function Translate() As String Local sStr, sNew, sOld As String Local nParams As Long If thinBasic_CheckOpenParens_Mandatory() Then thinBasic_ParseString sStr nParams += 1 If thinBasic_CheckComma_Optional() Then thinBasic_ParseString sNew nParams += 1 If thinBasic_CheckComma_Mandatory() Then thinBasic_ParseString sOld nParams += 1 End If End If If thinBasic_CheckCloseParens_Mandatory() Then If thinBasic_ErrorFree() Then Select Case nParams Case 1 Function = UCase$(sStr) Case 2 Function = ... something else Case 3 Replace sOld With sNew In sStr Function = sStr End Select End If End If End If End Function
AlternativethinBasic_LoadSymbol "Translate", %thinBasic_ReturnString, CODEPTR(Translate), %thinBasic_ForceOverWrite
In case the functions are not very performance demanding, you could reimplement them directly using ThinBASIC, store them in one file, for example REXX.tBasicU and reuse in projects.
Sample:
Function Translate( sStr As String, Optional sNew As String, sOld As String) As String Select Case Function_CParams Case 1 Return UCase$(sStr) Case 3 Return Replace$(sStr, sOld, sNew) Case Else MsgBox 0, "This function can only take 1 or 3 params" End Select End Function
Petr
Last edited by Petr Schreiber; 12-06-2013 at 18:11.
Learn 3D graphics with ThinBASIC, learn TBGL!
Windows 10 64bit - Intel Core i5-3350P @ 3.1GHz - 16 GB RAM - NVIDIA GeForce GTX 1050 Ti 4GB
Thanks, that's a big help.
Rexx tends to define a lot of functions with optional parameters. It would seem that I would need to deal with "optional" vs. "mandatory" commas, right parens, etc. to handle all the variant ways these functions can be used.
For example, I can have TRANSLATE(STR) or TRANSLATE(STR,NEW,OLD). So, I will get to a point after STR where I will either have a comma or a right paren. I will have to check for one or the other.
Now, if I check for a right paren and it's not there, am I supposed to do a "put back" when the thinBasic_Check... function returns FALSE? Or do I just keep trying other "Check" functions until one succeeds? --> [I see now what I need; never mind this sentence.]
If I have a syntax error, where I don't find a comma OR a right paren, what then? Do these modules just "stop" and let the thinBasic core detect a syntax error, or is there some way I can convey the fact that they were in my module and I found an unrecoverable syntax error, so that the message produced is more meaningful?
In the thinCore.INC, there are a number of variants of the 'check' functions, like
thinBasic_CheckComma
thinBasic_CheckComma_Mandatory
thinBasic_CheckComma_Optional
What is the difference between thinBasic_CheckComma_Optional and thinBasic_CheckComma (%true,%true) ?
What happens if I use a Mandatory version and the thing isn't there?
If I use an Optional version, and the token in question isn't there, does an automatic putback occur implicitly ?
Based on what is documented in thinCore.INC, it seems that thinBasic implements a recursive-descent parser. Is that the case?
Last edited by Robert Hodge; 12-06-2013 at 19:32.
Hi...
Hey that is a really interesting thing, i really like rexx but i never fined time or energy or
enough enthusiasm to do something.
A year ago i have use little bit Reginald REXX to test some GUI stuff with rexx cod.
This can be interesting to me especially if would be open source...
good luck
Aurel
Hi quatras9,
hope to reply to all of your question from top to bottom:
- regarding parsing functions related to comma or open or close parens I suggest to use the "*_Mandatory" or "*_Optional" version.
The "*_Optional" version will automatically putback to parsed token in case it is not the one searched.
The "*_Mandatory" version will automatically generate a runtime error if the token is not the one expected and script will stop execution.
The "parameter" version with 2 parameters (example thinBasic_CheckComma(p1, p2) ) is the first version developed when I started thinBasic. You can use it but is more complex and creates not so readable code.- Regarding runtime errors, thinBasic has a lot of internal checking when parsing and many automatica runtime errors will be fired if any inconsistencies will be identified. But regarding what is the syntax of a command, if it has optional or mandatory parameters, it is up to you (the programmer) to decide how it must be using the many parsing functions thinBasic gives you in SDK. If, at any time, you want to fire a runtime error, just use thinBasic_RunTimeError function.
- yes, all internal expression parsing functions are implemented using recursive descendant parser techniques plus some trick developed by me
Just one last advice: all thinBasic strings used in SDK are BSTR strings, dynamic strings. I suppose you are developing using PowerBasic so you should already be on the same line.
In the above post, Petr Schreiber gave you exactly an example on how to develop a function into a thinBasic module.
If you need something more complete, I can give you the full source code (Power Basic 9.x or 10.x) of a complete module implementing the above TRANSLATE function. In any case you can already find a complete example into SDK.
Ciao
Eros
Last edited by ErosOlmi; 12-06-2013 at 22:02.
www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000
The Rexx I have used the most, recently, is oo Rexx (http://www.oorexx.org/). It's a real nice implementation. My interest in Rexx at the moment is because I am trying to port some Rexx ISPF scripts to thinBasic for use with the text editor SPFLite. (www.spflite.com). We are about to release a new version with macro support, and are using thinBasic as the macro engine. The scripts I am trying to port are from TSO/ISPF Rexx and from old Tritus SPF. thinBasic is actually pretty close to Rexx in capabilities, but there is a good bit of syntax differences to overcome, and then there's the 7,000 lines of Rexx I am dealing with ...
Eros,
Thanks so much for your reply, it was very helpful.
If you were willing to pass along the source of a working module, that would be extremely helpful. As you may be aware, I'm working with George Deluca on SPFLite, and this is part of that effort. His code in written in PB, so I would end up doing the same. (Although my language of choice is C++, that's what he uses, so he gets to call the shots!)
Regards,
Robert
Attached to this post a complete thinBasic module that implements a new keyword named Rexx_Translate
I just implemented it partially, complete as needed
Check inside "thinRexx.bas" for detailed comments.
Compile using PB9x or PB10x
Use thinBAsic script example "thinRexx_Example.tbasic" to test the new module.
Hope this can help as a starting point of a great Rexx module
Ciao
Eros
www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000
Thanks so much, Eros, the thinRexx module is exactly the framework I need to get started. It has pretty much everything I need.
There is one area of modules I don't know if you handle or not, so here's my question.
A module is fine for introducing functions, subs and constants into the namespace. But, suppose you want to inject a new keyword into the namespace? For example, in Rexx, the DO statement is very general purpose, and it does by itself what basic does with DO, FOR, WHILE, UNTIL, REPEAT, LOOP, etc. It's not possible to make a one-for-one translation, but some automated assists are conceivably possible.
For example, in Rexx, an indexed loop that decrements is done with
whereas basic does it withdo i = 10 to 1 by -1 ... end
I can't envision any way to automated the closures. Basic has LOOP, NEXT, and (repeat) UNTIL whereas Rexx just has END. (Automating Basic to Rexx would actually be easier, BTW).for i = 10 to 1 step -1 ... next
But, the keyword BY in used in Rexx only for DO statements, so that BY -> STEP is a safe conversion. It would be interesting if I could do something like this:
Here, 'BY' would get converted to 'STEP' the same as if I had written this:USES "thinRexx" DIM I AS LONG FOR I = 10 TO 1 BY -1 ... NEXT
The problem, of course, is that (a) you don't have any API to define aliases in a module, and (b) even if you did, I don't think the USES processing time is the time when you handle pending alias definitions. Is that a fair assessment?USES "thinRexx" ALIAS STEP AS BY DIM I AS LONG FOR I = 10 TO 1 BY -1 ... NEXT
Mainly, I'd be interested in your assessment of this issue. Could such a thing (module-defined aliases) conceivably fit into your architecture?
Bookmarks