Hi Jim,
This update fix some issues and add some features:
Remove the limitation: You may not execute an OnError statement inside a Try / Catch / End Try statement.
OffError statement can be used safely anywhere, even in a Try / Catch / End Try statement.
From now on, it is no longer possible to call subroutines without parentheses (to avoid confusions with variables and to keep the same behaviour with functions).
draw =1
call draw
Before: call sub
Now works only: call sub()
It is safe (in fact it is safer than ONERROR label)
ONERROR mysub()
To do this, the subroutine must have no arguments. Otherwise the user will receive the appropriate error.
ONERROR mysub(1)
SUBROUTINE mysub(a)
END SUBROUTINE
COMPILE ERROR on line 1: Cannot pass arguments to a SUBROUTINE used by ONERROR statement.
ONERROR mysub()
SUBROUTINE mysub(a)
END SUBROUTINE
ERROR on line 1: SUBROUTINE 'mysub' expects arguments and therefore can not be used by ONERROR statement.
Documentation should be like this:
onerror label
onerror subroutine()
Execute a GOSUB at the specified label or call the specified subroutine when a runtime error occurs.
In order to use a subroutine it must have no argument.
The difference between the two ways of using the ONERROR statement is that if a label is used, all variables are shared with the called code and the program control may be resumed at the next statement with a Return statement in the called code.
When it is used with a subroutine all variables used within the subroutine, that have not been previously declared as Global, will be local to the subroutine and will not change the values in the calling code. In this case the program control will be returned when a Return statement is executed in subroutine or when the End Subroutine statement ise reached. (See more: [[Subroutine|Subroutine]])
Error traps are kept in a stack so that the last defined trap, that has not been removed with an OffError will be the active one.
For each SUBROUTINE/FUNCTION the required number of arguments is stored at compiling time.
So it's simpler and faster to check if the number of arguments match with SUBROUTINE/FUNCTION definition.
This is actually happening even before the SUBROUTINE/FUNCTION call.
This is needed also by ONERROR sub() to check the number of required arguments BEFORE using it in this syntax.
If you use a large program that use a number of symbols greater than 2000 it will not crash anymore.
r=1
try
call sub()
catch
print r #r 1-current recurse level, 2-we are still in subroutine
endtry
end
subroutine sub()
r=2
g=0/0
end subroutine
Before: program prints "2" because the program is still in subroutine level (never return).
After: program prints "1" - the program control is returned to TRY/CATCH level
onerror err
goto jump
try
jump:
print "we are in the middle of try part"
catch
print "catch it!"
endtry
print 0/0
end
err:
print "error!"
return
Before:
we are in the middle of try part
ERROR on line 9: Division by zero.
After: correct result because TRY/CATCH and ONERROR do not share the same stack anymore
we are in the middle of try part
error!
0
try
try
print "we are in second try"
goto jump
catch
print "catch it (second)!"
end try
jump:
catch
print "catch it (first)!"
end try
print 0/0
end
print "error!"
return
Before:
we are in second try
catch it (first)!
ERROR on line 13: Division by zero.
After: correct result because each CATCH know which is the matching TRY
we are in second try
ERROR on line 13: Division by zero.
call sub()
a=0/0
end
subroutine sub()
try
print "TRY in subroutine"
return
catch
print "never here!"
end try
print "never here too!"
end subroutine
Before:
TRY in subroutine
never here!
never here too!
After: correct behaviour because the TRY/CATCH trap from subroutine is removed when subroutine returns
TRY in subroutine
ERROR on line 2: Division by zero.
try
print 1
catch
print 2
endtry
Before:
00000000 OP_CURRLINE 1
00000002 OP_ONERRORCATCH 0000000e ___0_0
00000004 OP_CURRLINE 2
00000006 OP_PUSHINT 1
00000008 OP_PRINTN
00000009 OP_CURRLINE 3
0000000b OP_OFFERROR
0000000c OP_GOTO 00000016 ___1_0
0000000e OP_OFFERROR
0000000f OP_CURRLINE 4
00000011 OP_PUSHINT 2
00000013 OP_PRINTN
00000014 OP_CURRLINE 5
00000016 OP_CURRLINE 6
After:
00000000 OP_CURRLINE 1
00000002 OP_ONERRORCATCH 0000000d ___0_0
00000004 OP_CURRLINE 2
00000006 OP_PUSHINT 1
00000008 OP_PRINTN
00000009 OP_CURRLINE 3
0000000b OP_OFFERRORCATCH 00000014 ___1_0
0000000d OP_CURRLINE 4
0000000f OP_PUSHINT 2
00000011 OP_PRINTN
00000012 OP_CURRLINE 5
What is new is OP_OFFERRORCATCH label - which close try/catch trap and jump over the CATCH part.