Discussion:
Newbie question: Returning error result from a method
(too old to reply)
r***@gmail.com
2020-05-21 02:03:19 UTC
Permalink
Thanks to Rick McGuire for getting me started on ooRexx. Here's another noob question: I want to handle error conditions in methods.

In TSO REXX there's no such thing as a method, but anywhere in my program I can "call abend <msg>" and an internal Abend routine displays the message and does an Exit 8. Inside an ooRexx method my Abend subroutine apparently isn't visible, so I need another way to signal a bad call.

1) Easy first question: Is there a way to ~make~ an internal subroutine visible to a method? I'm guessing there is not, but if it is it would probably be simplest.

2) Failing that, I can try "return <msg>". But when I try that, the message doesn't show up in RESULT, as I would have expected (nor in RC, which I expected less). Maybe the RETURN statement is only for functions.

3) I tried "exit <msg>", which worked in one situation but not in another: During the init method I used "exit 8", but the result back in the calling program was just RESULT. In another method I used "exit 'No error'", and the result was populated that time. Maybe RESULT just doesn't work with any INIT method? Seems kind of artificial, but what do I know? I can post a short program demo if needed.

4) Do I have to use a RAISE ERROR statement? I've never had occasion to do that before, but it kind of makes sense.

Recommendations gratefully accepted.
Rick McGuire
2020-05-21 13:27:40 UTC
Permalink
Post by r***@gmail.com
Thanks to Rick McGuire for getting me started on ooRexx. Here's another noob question: I want to handle error conditions in methods.
In TSO REXX there's no such thing as a method, but anywhere in my program I can "call abend <msg>" and an internal Abend routine displays the message and does an Exit 8. Inside an ooRexx method my Abend subroutine apparently isn't visible, so I need another way to signal a bad call.
1) Easy first question: Is there a way to ~make~ an internal subroutine visible to a method? I'm guessing there is not, but if it is it would probably be simplest.
No, (well, mostly no. You can create internal routines inside the code block of the method, it those are only visible inside that code block). Better would be to create an external routine using ::routine, which will be visibly globally.
Post by r***@gmail.com
2) Failing that, I can try "return <msg>". But when I try that, the message doesn't show up in RESULT, as I would have expected (nor in RC, which I expected less). Maybe the RETURN statement is only for functions.
This should work. I would need to see an example of what you are really doing in order to suggest what you might be doing wrong.
Post by r***@gmail.com
3) I tried "exit <msg>", which worked in one situation but not in another: During the init method I used "exit 8", but the result back in the calling program was just RESULT. In another method I used "exit 'No error'", and the result was populated that time. Maybe RESULT just doesn't work with any INIT method? Seems kind of artificial, but what do I know? I can post a short program demo if needed.
Exit from a method just terminates the current code block (basically the same as Return from that context).
Post by r***@gmail.com
4) Do I have to use a RAISE ERROR statement? I've never had occasion to do that before, but it kind of makes sense.
RAISE SYNTAX would be more appropriate. This will propagate all the way back to the top level unless trapped by a SIGNAL ON SYNTAX. There are even some defined syntax error numbers reserved for USER messages where you can fill in whatever message text you want.
Post by r***@gmail.com
Recommendations gratefully accepted.
Robert Bridges
2020-05-21 18:20:44 UTC
Permalink
Here's a sample program, pared down to the bare essentials (almost):

/* Code begins */
ox=.class~new('X')
say ox rc result
ox~add('Therefore')
say ox rc result
exit

::class Class
::attribute Idx
::attribute Txt

::method Add
expose txt
txt="@"
return 0

::method init
expose txt
use arg idx
if idx<>'@' then return "Error"
txt=''
/* code ends */

When I run this, I get:

a CLASS RC RESULT
a CLASS RC 0

I get no RESULT from the INIT method, I suppose because it's busy passing back the object itself. I get the same if I use EXIT instead of RETURN. I think when I reported that I got no result back using RETURN, in my last post, I must have tested only the INIT method.

"RAISE SYNTAX"? I ignored that option before because the errors I have in mind don't have to do with REXX syntax. But your point about it propagating all the way back to the main program is a good one, because I've already discovered that SIGNAL ON USER xxxx cannot be seen (so to speak) more than one method deep. That is, using this program:

/* code begins */
signal on user abend
os=.super~new('@')
os~sub
exit

abend:
oerr=condition('O')
say '***' oerr['RESULT']
exit

::class Super
::method init
use arg idx
if idx<>'@' then raise user abend return 'Super~init error'
say 'Super~init worked'
::method Sub
ox=.subord~new
ox~err
say 'Super~Sub worked'

::class Subord
::method Err
raise user abend return 'Subord~err error'
say 'Subord~err worked'
/* code ends */

I run this and I get "*** Super~init error", as should happen. But if I fire up the Super object with '@' instead, I get this:

Super~init worked
Super~Sub worked

I infer that my SIGNAL ON USER in the main program is visible inside the methods of the Super class - but when a method of the Super class calls a method of the Subord class, USER ABEND conditions are no longer trapped.
Rick McGuire
2020-05-21 20:33:58 UTC
Permalink
Post by Robert Bridges
/* Code begins */
ox=.class~new('X')
say ox rc result
ox~add('Therefore')
say ox rc result
exit
::class Class
::attribute Idx
::attribute Txt
::method Add
expose txt
return 0
::method init
expose txt
use arg idx
txt=''
/* code ends */
a CLASS RC RESULT
a CLASS RC 0
I get no RESULT from the INIT method, I suppose because it's busy passing back the object itself.
The INIT method is called by the class object's new method, which ignores any return value, so that return value is just lost. There's no way to return an error value from an INIT method.

I get the same if I use EXIT instead of RETURN. I think when I reported that I got no result back using RETURN, in my last post, I must have tested only the INIT method.
Post by Robert Bridges
/* code begins */
signal on user abend
os~sub
exit
oerr=condition('O')
say '***' oerr['RESULT']
exit
::class Super
::method init
use arg idx
say 'Super~init worked'
::method Sub
ox=.subord~new
ox~err
say 'Super~Sub worked'
::class Subord
::method Err
raise user abend return 'Subord~err error'
say 'Subord~err worked'
/* code ends */
Super~init worked
Super~Sub worked
I infer that my SIGNAL ON USER in the main program is visible inside the methods of the Super class - but when a method of the Super class calls a method of the Subord class, USER ABEND conditions are no longer trapped.
It has more to do with the call stack. The RAISE USER instruction terminates the current execution level and raises the condition in the calling level. If there is no trap active at that level, then the condition is ignored. Method calls follow the execution rules for external routines and don't inherit any signal traps, and they also can't access any of the labels in the calling code.
Loading...