WHEN ERRor in PROCedures and FuNctions allowed?

Anything QL Software or Programming Related.
Post Reply
User avatar
ql_freak
Gold Card
Posts: 481
Joined: Sun Jan 18, 2015 1:29 am

WHEN ERRor in PROCedures and FuNctions allowed?

Post by ql_freak »

Can WHEN ERRor be safely used in S(uper)BASIC PROCedures and FuNctions?

It seems not, because the following does not work (I have a similar construct in another SuperBASIC program, where the WHEN ERRor is outside of a PROCedure/FuNction, and there this construct (which should simulate a C++ try {...} catch {...}) seems to work.

But the Following example just prints "In WHEN Error" and afterwards WHEN ERRor processing is still on. It seems the WHEN ERRor:END WHEN in 1210 does not switch off error processing. I have also tried a (IMHO not necessary) CONTINUE before the first END WHEN (line 1160), but this doesn't change the behaviour. The example program below is a stripped down version of a program, I want to develop. In reality the user should be able to specify the CON channel, the CON channel con$ in 259 is only the initial CON channel which can be opened on any QL. In the real program the user can input the CON channel (with my improved EDLINE$-function) and retry or quit with ESC.

Code: Select all

100 REMark Test Program for WHEN ERRor in FuNction
140 :
180 REMark SB channels:
220 c%=5: REMark SB CONsole-channel for normal in-/output (from/to screen)
259 con$='CON_252x200a0x0':OPEN#c%,con$:REMark Initial CON channel
500 init
540 PRINT#c%,'Hello in new CON channel'
660 CLOSE#c%
10000 :
10040 DEFine PROCedure init
10050   REPeat _setCon_
10160     newcon$='CON_454x460a512x30'
10200     IF checkCONchan$(newcon$)=''
10240       PRINT#c%,'Bad CON channel specification':stop
10320     END IF
10360     EXIT _setCon_
10400   END REPeat _setCon_
10440   CLS#c%:PAPER#c%,4:INK#c%,0:CLS#c%
10480   PAPER#c%,4:in:PRINT#c%,'Just a test program for WHEN ERRor'
10920 END DEFine init
10960 :
11000 DEFine FuNction checkCONchan$(con_$)
11040   LOCal _catch%
11080   REMark REPeat _checkCon_
11120     _catch%=0
11160     WHEN ERRor :catch%=1:PRINT'In WHEN ERRor':CONTINUE:END WHEN
11200       OPEN#c%,con_$&'_512'
11210     WHEN ERRor :END WHEN
11220     PRINT'Before IF _catch%'
11240     IF _catch%
11320       PRINT"Before RETurn ''":RETurn ''
11330     END IF
11360     REMark EXIT _checkCon_
11400   REMark END REPeat _checkCon_
11440   PRINT'Before ...:RETurn con_$':con$=con_$:RETurn con_$
11450 END DEFine checkCONchan$


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
Andrew
QL Wafer Drive
Posts: 1032
Joined: Tue Jul 17, 2018 9:10 pm

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by Andrew »

I tried to use When Error in one of my programs. I gave up because I found out that the When Error will act upon all of the program and all errors will trigger it And, obviously, different errors need different When Error clauses and I could not find a reliable way to link a specific error to a specific when error clause.
Also WHEN ERRor clauses will also remain in force despite NEW, CLEAR, LRUN, LOAD, MERGE and MRUN.
I find that QLib error management is way more reliable and versatile and can be used also in uncompiled Basic programs.


User avatar
dilwyn
Mr QL
Posts: 3057
Joined: Wed Dec 01, 2010 10:39 pm

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by dilwyn »

Here is an extract from Simon Goodwin's QL ROM Bugs articles from QL World, explaining the shortcomings of WHEN that were known at the time he wrote the articles.
WHEN WILL IT WORK?

From the start, QL ROMs contained WHEN keywords to trap errors and monitor variable-values. At first they did nothing at all; on ROMs from "JS" onwards they sometimes work, and sometimes they just crash the machine.

Sinclair have been understandably reluctant to explain how WHEN trapping should work, as they've never produced a QL ROM that can do it properly. Apparently they persuaded Jan Jones, author of the interpreter and 'The Definitive SuperBASIC Handbook', to omit a chapter on WHEN handling from her otherwise-definitive tome.

IN THEORY, WHEN

The idea is to put a WHEN ERRor statement somewhere in your program, followed by program lines to be executed in the case of an error, and rounded off with an END WHEN statement. The computer keeps track of the most recent WHEN ERRor block, and jumps into it if an error occurs, without printing the usual cryptic message or stopping the program.

You check the line and type of the error by reading the values of new functions: ERLIN and ERNUM. ERNUM returns internal error-codes between -1 and -21. Other functions let you check for a given error, without knowing the internal code: ERR NC is true (1) if the error was 'not complete', ERR BN indicates 'bad name', and so forth. Unfortunately someone typed a BRA where they should have put a BSR, so any attempt to check ERR DF, 'drive full', crashes the "JS" ROM.

The new REPORT procedure prints standard error messages. If you already use that name, or any of the other new ones, in your BASIC, you'll have to change it. REPORT on its own indicates the last error with a message to channel 0. Codes from -21 to -27 call up other text: REPORT -24 gives 'F1..Monitor F2..TV', for example.

There's no check on the number you supply, but only 27 messages are in the standard format, so beware: REPORT -28 and its brethren print a very, very long string of gibberish. REPORT 1,-19 prints 'not implemented' to channel 1; -19 is the polite code that a routine should use to indicate that it doesn't work yet.

The code for WHEN ERRor is not usually that kind. Errors in functions often crash the machine if WHEN trapping is in force; SQRT of a negative expression will do the trick, as will INKEY$ at the end of a file.

WHEN ERRor is extremely persistent - you can type LOAD or NEW and the computer will still try to trap your errors to a non-existent routine. Similar problems occur if you delete an active WHEN statement, or type one as a direct command.

Tony Tebby's Supertoolkit clears WHEN after commands like NEW and LOAD, and fixes the ERR DF mistake, but it can't help with the other problems. Digital Precision's TURBO compiler gives you reliable WHEN ERROR trapping anywhere in a program, on all QL versions, but of course it doesn't fix the interpreter.

Another WHEN option in the "JS" ROM lets you monitor variable values. A block starting WHEN VAR>10 will only be executed when the condition becomes true; every time VAR is set BASIC checks the new value, and calls the WHEN routine if the value of VAR exceeds 10. Unfortunately this doesn't work reliably on any QL version, either; sometimes it gives a 'bad name' report, or calls the routine more than once.

---

The WHEN routines are still unfinished in the "MG" ROM, although the trivial ERR DF bug has been fixed.

---

WHEN ERROR and WHEN Variable had terrible bugs under Sinclair's interpreter, but work well under Minerva. WHEN ERROR can intercept any report, whereas error-trapping during calculations used to crash the QL and Thor.

WHEN Variable runs a block of code whenever a simple variable matches a condition. For instance, you can write:

WHEN x>511
PRINT #0;"Horizontal overflow."
x=511
END WHEN

This code is executed whenever X is assigned a value greater than 511, then the program continues. Sinclair ROMs ignored assignment of FOR counters, and could crash if more than 20 WHEN blocks were active, or a WHEN block was deleted. Minerva does not have these bugs, but it cannot yet trap array access, or the implicit assignment of INPUT and READ.

---


User avatar
ql_freak
Gold Card
Posts: 481
Joined: Sun Jan 18, 2015 1:29 am

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by ql_freak »

I know of these horror stories of WHEN ERRor (I do not need WHEN variable) but after all I have read, I thought the most problems have gone at least with Minerva. Have I told, that I have tested the example above with Minerva on sQLux, QPC2 behaves even worse with this code.

And as I have written, the principle (emulate a try {...} catch {...} [try: except: in Python] Exception Clause) seems to work outside of PROCedures and FuNctions.

The WHEN ERROR should have a possibility, to switch off _ALL_ error processing inside the WHEN ERRor clause with a command like ERRor OFF and then continue to the statement following the statement, which caused the error (what Is in principle, what exception handling does in C++, Python, Java, ...). BTW: In C you can do a much more restricted error catching with longjmp(), most Compilers have it (at least Lattice C and so nearly sure C68).


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
tofro
Font of All Knowledge
Posts: 3081
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by tofro »

You seem to have both a variable _catch% (11160) and catch% (everywhere else, without the underscore).

_catch% doesn't catch catch%. :)

Also, the WHEN ERRor routine shouldn't use LOCal variables (or be very careful about it). It might be called from places where the LOCals are not in scope at all. This will almost certainly crash the program.

If you observe some simple rules, in my experience, WHEN ERRor works just fine at least on Minerva and SBASIC.


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
RalfR
QL Wafer Drive
Posts: 1177
Joined: Fri Jun 15, 2018 8:58 pm

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by RalfR »

Error catching is really only necessary for procedures, and I consider Q_ERR_ON/OFF to be much better for that, because you can catch the error where it occurs and handle it there. WHEN ERRor is far too global for that.


7000 4E75
User avatar
ql_freak
Gold Card
Posts: 481
Joined: Sun Jan 18, 2015 1:29 am

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by ql_freak »

tofro wrote: Thu Mar 20, 2025 7:28 am _catch% doesn't catch catch%. :)

Also, the WHEN ERRor routine shouldn't use LOCal variables (or be very careful about it). It might be called from places where the LOCals are not in scope at all. This will almost certainly crash the program.
Thanks for the _catch%/catch%. I have now corrected it (all changed to _catch%) and REMarked the LOCal. But in my example this would make no difference, cause the console will be opened and then (because of the CONTINUE in first WHEN ERRor:...:END WHEN) the statement

Code: Select all

PRINT'Before IF _catch%'
should be executed. But the program only prints "In WHEN ERRor" and afterwards (program has terminated) WHEN ERRor processing is still on, the

Code: Select all

WHEN ERRor :END WHEN
(11210) seems not to be executed.

And Ralf, of course in this case I do not need WHEN ERRor, I could use FOPEN() and check it's result. But I think there are some machine code functions which can fail (program abort) which cannot be catched by Q_ERR_ON. If WHEN ERRor would work correctly, my example shows, that you can simulate a try...catch which is now common in modern languages. As I have written, I have a working example where WHEN ERRor is outside of PROCedure/FuNction.


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
User avatar
RalfR
QL Wafer Drive
Posts: 1177
Joined: Fri Jun 15, 2018 8:58 pm

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by RalfR »

ql_freak wrote: Sat Mar 22, 2025 5:40 pmBut I think there are some machine code functions which can fail (program abort) which cannot be catched by Q_ERR_ON.
Q_ERR_x only works with machine code procedures, not with functions!


7000 4E75
User avatar
ql_freak
Gold Card
Posts: 481
Joined: Sun Jan 18, 2015 1:29 am

Re: WHEN ERRor in PROCedures and FuNctions allowed?

Post by ql_freak »

That's what I have said!


http://peter-sulzer.bplaced.net
GERMAN! QL-Download page also available in English: GETLINE$() function, UNIX-like "ls" command, improved DIY-Toolkit function EDLINE$ - All with source. AND a good Python 3 Tutorial (German) for Win/UNIX :-)
Post Reply