Semantics for Error Handling Word Set _________________________________________
See the file 'Examples.Errors' for examples of usage of the words described in this section.
THROW and CATCH provides the tools for creating efficient error handling at multiple levels in a structured manner.
An error can occur by execution of THROW, ABORT or ABORT" or if an error occurs in one of the words of the Forth kernel. No matter how and where the error occurred, control is always transferred to THROW. This is to enable an application to deal with errors through the use of CATCH.
THROW collects error diagnostics and returns control to CATCH, or in the absence of any CATCH, the error is typed out and control is transferred to QUIT.
In the AForth implementation of ANS Forth, an additional word THROWN? is provided to selectively collect various error diagnostics in order to process an error caught by CATCH. THROWN? is a non-standard word provided for easy interfacing to RISC-OS and to aid conversion from BASIC to Forth.
CATCH Error
( i*w w -- j*w 0 ) no THROW recieved
or ( i*w w -- i*w n ) THROW recieved
Push an error interception frame onto the return stack and execute the word represented by the execution token w (as with EXECUTE). The frame remembers the current stack depth. When the word w has been executed, CATCH pushes an error indicator n onto the stack and continues execution at the point after CATCH.
If the error indicator n is zero, no THROW was recieved. Otherwise, if n is non-zero, a THROW was received and n is the value THROWn. In this case the stack depth is the same as before executing CATCH, not counting the input parameter, w. Since the stack depth is known, the items may be dropped, if these have been invalidated by the error condition.
THROW Error
( k*w 0 -- k*w ) not thrown
or ( k*w n -- k*w n ) thrown
If the top of the stack is zero, then discard it. Otherwise if top of stack is non-zero, pop the topmost error interception frame from the return stack. Then call the error handler and continue execution at the point after the CATCH that installed this error interception frame. The stack depth is now the same as just before execution of CATCH, apart from one extra item n, which is the argument passed to THROW. If no error interception frame is found, the return and data stacks are emptied, the error handler is called to display the error message, and lastly control is transferred to QUIT. The case where an error interception frame is found is described under CATCH.
THROW can take the address of a standard RISC-OS error block as input and also I/O reason codes (ior in stack diagrams), as such are in fact pointers to RISC-OS error blocks (I/O reason codes are extensively used by the words of the File Access word set). Negative values of n are reserved for this implementation and ANS standard assignments. Other values are available for applications.
Due to the way THROW is implemented, it is illegal to pass values greater than 32768 (&8000 hexadecimal) to THROW, unless of course, the value is a pointer to a standard RISC-OS error block. That is, a user application may only pass to THROW values in the inclusive range 1-32767 or standard RISC-OS error block addresses.
THROWN? RISCOS
( u -- w ) or ( u -- c-addr u )
This is a non-standard word, and thus should not be used in portable code.
THROWN? returns information from the error relating to the last THROW processed. This can be used to extract error diagnostics and produce an intelligible message before resuming normal execution.
Below is shown the input parameters currently supported and the corresponding information that will be returned (all codes not described here or codes which are reserved, return zero):
( 0 -- n )
n is the error number. If a standard RISC-OS error block was the THROWn value, the error number is extracted from the first word of this block.
( 1 -- c-addr u )
c-addr u describes the error string containing the raw error message --- no other information as location of error or file line number is included. If a standard RISC-OS error block was passed to THROW, c-addr u is the string contained in this error block.
( 2 -- n )
a-addr is the address of where the error occurred. a-addr actually points to the opcode following the BL or SWI opcode which called the error handler.
( 3 -- c-addr u )
c-addr u is a string containing the name of the word in which the error occured. Note that this may in some rare cases yield an odd or incorrect result. If the error handler failed in extracting this information, the null-string is returned.
( 4 -- u )
u is the line of the file, where the error occurred in. If the error did not occur while interpreting from a file, u is zero.
( 5 -- c-addr 0 )
reserved for future expansion.
( 6 -- a-addr )
a-addr is the address of a standard RISC-OS error block. a-addr can be passed on to Wimp_ReportError. It is only applicable in the case that a standard RISC-OS error block was passed to THROW.
Below is a list of all the error messages of AForth. Each entry in the list has a header containing the error message followed by a description of how and when this kind of error may occur.
'Definition not finished'
Some control flow structure has been badly nested or terminated or the data stack depth has changed during the compilation of the last definition. It could also mean that you forgot the ending ; (semi-colon) when you entered a definition from the command line.
'Word ccc not found', where ccc stands for any string.
Either you have misspelled a wordname or you have forgotten the terminating ; (semi-colon) at the end of the previous definition.
'Line too long'
Either the line being parsed from a file is too long or there is no line terminator at the end of the file.
Common Errors _________________________________________________________________
Below is a list of commonly encountered problems/errors which may be of help to the unexperienced Forth programmer.
If none of these error explanations below solve the problem of question, ask a Forth expert or send me a mail with a thorough description of your problem. I'm not a Forth expert compared to the *real* experts, but I'm working on it :-)
Badly nesting of >R and R>.
Errors: 'Address Exception' or similar exceptions
Always ensure that there are as many >R as there are R> within a forth word. Also within a DO LOOP the above mentioned words have to be properly nested. Furthermore, it is illegal to access items stored on the return stack from within a DO LOOP, as DO LOOP uses the return stack for the loop parameters. Any violation of these restrictions will most certainly crash the computer. The restrictions naturally also applies for the words 2>R and 2R>.