From: Rony G. F. <Ron...@wu...> - 2022-06-12 10:39:50
|
Hi Mike, many questions... :) Firstly one thing you should know: ooRexx is backwardly compatible with Rexx, this way one can develop and run classic Rexx programs including the Rexx scoping rules (which variables and labels can be seen from which part of a Rexx program). Ad ooRexx scopes (from my slides): * "Standard Scope": Determines which labels are visible o Labels are only visible within a program (until the end of the program or until the first directive led in by a double colon ::, whatever comes first) o Labels within of ::ROUTINE and ::METHOD directives are only visible within the code of these directives * "Procedure Scope": Determines, which variables of the caller are visible (accessible) from within the called internal routine (procedure/function) o Internal routines (labels), without a PROCEDURE statement: All variables of the calling part of the program are accessible + Internal routines (labels), followed by a PROCEDURE statement – Variables of the calling part of the program are not accessible (are hidden) # "Local scope" However: with the help of the EXPOSE subkeyword on a PROCEDURE statement one can deliberately define direct access to variables of the calling part of the program * "Program Scope" (new in ooRexx): Determines that all classes and routines defined in a program are accessible + Local classes and routines cannot be hidden/overwritten + Classes and routines can be defined to be public o In addition, this scope determines, that public classes and public routines of called or required (::REQUIRES directive) programs become accessible ● Attention! + If different programs are called one after the other, and contain public classes or public routines with the same names, then those classes/routines are accessible that are defined in the last called program * "Routine Scope" (new in ooRexx): Defines its own scope for + Labels ("standard scope") and + Variables ("procedure scope") o Accessing classes and routines is determined by the "program scope" * "Method Scope" (new in ooRexx): same as "Routine Scope" plus o Direct access to attributes ● Within a method it is possible to use the EXPOSE statement (must be the first statement in the method routine) to list those attributes of the class which should be made directly available for access from within the method routine o Determines which attributes can be accessed directly from within a method + There are two types of methods which determine the accessibility of attributes # Methods that are assigned to classes * Method and attribute directives defined after a class directive get assigned to that class * Expose and share the same set of instance/object attributes # "Floating methods" (advanced concept, can be used for dynamic programming) * Methods which are defined before a class directive are called "floating methods" * All floating methods can expose and share the same attributes with each other * Hint: accessing floating methods is possible via the environment symbol .METHODS from within the program where they are defined --- Ad ooRexx directives: ooRexx directives start with two colons (::) and instruct the ooRexx interpreter to do something at that point in time for us, before starting our program with line # 1. E.g. the "::requires someRexxProgram" causes the interpreter to call "someRexxProgram" if it was not yet called, otherwise it would reuse all public classes and public routines of "someRexxProgram". ooRexx directives are not available to NetRexx and will cause a syntax error. --- Ad BsfContextVariables(): this is a normal external Rexx function, hence you could load it with RxFuncAdd(), but I would advise against it. You can include BSF.CLS (which loads all external BSF4ooRexx functions and establishes the camouflaging support such that strictly typed Java classes and Java objects can be interacted with as if they were dynamically typed ooRexx classes and ooRexx objects) in two ways: * call BSF.CLS /* each call will run BSF.CLS and replace definitions of prior calls of BSF.CLS */ * ::requires BSF.CLS /* the first time ooRexx sees this directive it will call BSF.CLS but reuse it if it encounters later ::requires BSF.CLS in other ooRexx programs */ BsfContextVariables() allows one to get all currently defined variables as a directory (index is name of the variable, item the current value) for which in the meantime alternatives exist (.context~package~variables). BsfContextVariables() allows you to set multiple Rexx variable in the scope where you invoke it, if you supplied a directory with all variables that should get defined. For this usage I would suggest BsfContextVariables(). --- Ad fetching data from external sources. ooRexx 5 gained the ability to use the ADDRESS keyword instruction to redirect stdin, stdout and stderr from/to ooRexx if desired. To do so you define what collection you want to use from ooRexx, e.g. a stem or an array. Not being familar with Netrexx pipes here a hypothetical pipe where the data comes from Rexx and the result is piped into Rexx again. So please excuse if the following pipe is syntactically wrong, but I think you get the idea: command='pipe console | sort | console' -- intensions read from the console, sort, output to console arrIn =.array~of("Max", "und", "Moritz", "diese", "beiden", "konnt", "...") arrOut=.array~new -- command gets input from ooRexx' arrIn, places stdout into arrOut ADDRESS SYSTEM command WITH INPUT USING (arrIn) OUTPUT USING (arrOut) -- now we need to postprocess the data received from the NetRexx pipe -- assuming that each line is in the form of "varName=varValue", -- lines that start with an asterisk (*) get ignored -- create a directory of varName/varValue entries dir=.directory~new do line over arrOut -- process output of pipe line by line parse var line varName '=' varValue dir~setentry(varName,varValue) -- setentry will uppercase the index varName automatically end -- now you decide what do to with the directory: use it to set Rexx variables in the current -- context (in this very section of the code) or maybe return it to a caller who could use -- the directory to set variables in its context -- call BsfSetContextVariable("set",dir) -- will set the Rexx variable using dir -- or: --return dir -- will return the directory to the caller You probably get the idea and can assess better how you can use the ooRexx and BSF4ooRexx infrastructure. HTH ---rony On 6/12/2022 4:56 AM, hp...@we... wrote: > Hi Rony! > > Once started from the promise/allegation, NetRexx Pipelines would > work the same as the role model on VM/CMS I planned to eliminate > OS/2 Pipelines in a ooRexx program -- and René agreed to help -- > we are now at the detail point, how do I get BSFContextVariables > to do what I need? Currently I'm not convinced to be still on > track, but that's my impression which could be wrong. > > Let me picture the idea I have about REXX variable pools. It may > be the source of failure because too coarse or completely wrong or > too much influenced by REXX as I know it from VM/CMS. So please > holler if I have the wrong picture. > Every REXX program has its own variable pool. Subroutines within > the same file share this pool _unless_ protected by "procedure" > which optional may share a selected set of variables by "expose". > Within ooRexx it's just the other way round, objects and methods > are protected "like lepers", what might help in vast program files > where by chance use of same variable names might occur. So each > "entity" has a variable pool of its own. > > This "keep 'em separated" is absolute when running NetRexx > Pipelines from ooRexx, since stages like var, stem and alike all > fail (from an ooRexx-centric point of view). The solution using > the stack to bring an ooRexx stem's content to the NetRexx pipe > shown by Gil Barmwater works, highly likely it could also work > backwards. Alas, NetRexx Pipelines lack the stack stage. > > At the moment I have trouble with BsfContextVariables() in two > ways, theoretically and in practice. > Theoretically with respect to the current variable pool involved: > > Am 10.06.2022 um 16:00 schrieb Rony G. Flatscher: >>> [...] >>> Please define "current" ;) >> >> It is the context of the Rexx code executing >> BsfContextVariables(). ;) > > In that case a simple a = b would set the same variable A as does > BsfContextVariables('Set', a, b). So there is for sure something I > did not grasp yet. Nonetheless I gave it a try -- the trouble in > practice: > The first replacement of OS/2 Pipelines by NetRexx P. would be: > >> ripe = '@java -cp "', >> || value("NETREXX_HOME", , "ENVIRONMENT"), >> || '\lib\NetRexxF.jar;', >> || value("CLASSPATH", , "ENVIRONMENT"), >> || '"' 'org.netrexx.njpipes.pipes.runner' >> fn = vilma.ini >> '' ripe '"(sep !) <' fn '!nxvarload' > > with nxvarload being a draft of a future varload stage, a current > snapshot of it: > >> /* nxvarload.njp: NetrexX VARLOAD, still incomplete */ >> import org.netrexx.njpipes.pipes. >> class nxvarload extends stage >> method run() >> do /* who needs this? */ >> addpipe (bs end ? sep !) *in:!a: fanout!strip!locate!*in:?a:!*out: >> loop forever >> line = Rexx readto() >> parse line.upper sc +1 vn (sc) sv /* UPPER to force keyword SYMBOLIC */ >> if sc <> '*' then BSFContextVariables("Set", vn, sv) >> end >> catch StageError >> rc = rc() >> end >> exit(rc*(rc<>12)) >> ::requires BSF.CLS > > (In case you wonder about the addpipe, 'the Book' specifies, > "varload strictly does not delay the record." That implies, even > without explicit operation description, varload copies records to > the primary output stream.) > > Problem: without ::requires directive BSFContextVariables() is > unknown, with it the PIPC compiler or translator dislikes the > colons of the directive. Frankly, methinks it's a bit contorted to > use a ooRexx directive and function within a NetRexx stage, but > without know-why I am pretty helpless. > >>> [...] >> There is no choice available to use any other pool than the >> context one, i.e. the variable pool of the location where your >> program runs BsfContextVariables(). (You could have a routine >> which collects the pipe results and returns it and at the receiver >> side issue the BsfContextVariables() with that data.) > > When I have collected pipe results in ooRexx I see no need for > BsfContextVariables(). Sorry, but I would access the results > collection directly. > >> [...] >> If you want to set variables (instead of interpret) you can use >> the value() BIF (built-in function) like this: >> >> call value hi, 'hi, my beloved world' >> say hi /* will say 'hi, my beloved world' > > Nice, but how do I get that "hi, my beloved world" from NetRexx > Pipelines to that BIF value in line one? > > Please advice. > M. |