• Newbie question: Returning error result from a method

    From robhbridges@gmail.com@21:1/5 to All on Wed May 20 19:03:19 2020
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rick McGuire@21:1/5 to robhb...@gmail.com on Thu May 21 06:27:40 2020
    On Wednesday, May 20, 2020 at 10:03:21 PM UTC-4, robhb...@gmail.com wrote:
    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.


    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.


    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).


    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.


    Recommendations gratefully accepted.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert Bridges@21:1/5 to All on Thu May 21 11:20:44 2020
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Rick McGuire@21:1/5 to Robert Bridges on Thu May 21 13:33:58 2020
    On Thursday, May 21, 2020 at 2:20:45 PM UTC-4, Robert Bridges wrote:
    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.

    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.

    "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.

    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)