21.4. Levels of error handling

[<<<] [>>>]

The error correction code should be simple and carefully designed. If an error happens while executing the error correction code the interpreter will terminate the program code or at least will go up to the next level of exception handling.

When the interpreter executes a jump to the error correction code caused by an error the ON ERROR GOTO functionality is switched off automatically until a new ON ERROR GOTO instruction is executed. This is done to prevent infinite looping caused by errors in the error correction code. The error correction code therefore usually executes an ON ERROR GOTO statement pointing to the start of the error correction code itself immediately before the execution the statement RESUME.

At the same time an error correction code can not have its own error correction code. If an error correction code uses the ON ERROR GOTO statement to specify its own error correction code it looses the resume point when an error occurs. In other words the remembered point of code where to resume after error correction is always the statement where the last error occurred. There is only a single resume point during execution and there is no stack of resume points.

The error handling statements use labels. Labels in ScriptBasic are local. You can not refer to a label in a function or subroutine from outside and vice versa. There is no need to do so with the error handling functions as well. The issue is that the jumping instruction is executed some time after the label was used.

What happens when an statement ON ERROR GOTO is used in function X and the error happens in function Y called from function X. Will the code jump from one function to the other?

sub X
on error goto ErrorLabel
print "starting sub Y\n"
call Y
print "sub Y returned\n"
exit sub
ErrorLabel:
print "an error occurred while executing Y\n"
end sub

sub Y

error 1 end sub

call X end

will print

starting sub Y
an error occurred while executing Y

The answer seems to be yes, but the case is not so simple. When the error occurs the interpreter sees that there is no ON ERROR GOTO statement currently in effect in the subroutine Y. Therefore it handles the error and terminates the execution of the subroutine Y. The subroutine returns and the error is inherited to the statement CALL invoking Y. The interpreter gets into the error condition again and now, at this level of execution there is an effective ON ERROR GOTO statement, which is executed.

To see that this really happens this way see the following example:

sub X
on error goto ErrorLabel
print "starting sub Y\n"
call Y
print "sub Y returned\n"
exit sub
ErrorLabel:
print "an error occurred while executing Y\n"
Flag = 0
Resume
end sub

sub Y print "Y started\n" if Flag = 1 Then error 1 end if print "Y finishes\n" end sub

Flag = 1

call X end

will print

starting sub Y
Y started
an error occurred while executing Y
Y started
Y finishes
sub Y returned

In this code the subroutine Y causes error if the global variable Flag is 1. The error correction code sets this variable to zero and corrects the error with this action. After resuming the execution the code continues at the subroutine call and not at the error statement. This shows that the error condition does not jump out of the function. It rather terminates the function and propagates the error code up to the caller until the main program level is reached and program execution is terminated or there is an effective ON ERROR GOTO or ON ERROR RESUME statement.

When an ON ERROR GOTO/RESUME statement is executed it overrides the settings of the previously executed ON ERROR GOTO/RESUME statement, which is in effect. But it does not override the settings of any higher level settings, because those are not currently in effect and the settings are restored when the program returns from the actual function or subroutine. For example:

Global const nl ="\n"
sub ErrorSub
  on error goto ErrorLabel
  error 1
  print "No error has occurred in the function. Weird.\n"
  goto FinishLabel
ErrorLabel:
  print "An error has occurred inside the sub\n"
  print "and now generating another error, which is not

handled by the subroutine.\n" error 2 FinishLabel:

end sub

on error goto ErrorLabel

call ErrorSub

print "No error" goto FinishLabel

ErrorLabel: print "Error code: ",error(),nl

FinishLabel: end

will print

An error has occurred inside the sub

and now generating another error, which is not

handled by the subroutine.

Error code: 2

Note that the ON ERROR GOTO setting of the module outside the subroutine remained valid although another ON ERROR GOTO setting was issued inside the subroutine.


[<<<] [>>>]