www.delorie.com/gnu/docs/gforth/gforth_95.html   search  
 
Buy GNU books!


Gforth Manual

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.8.6 Exception Handling

If a word detects an error condition that it cannot handle, it can throw an exception. In the simplest case, this will terminate your program, and report an appropriate error.

doc-throw

Throw consumes a cell-sized error number on the stack. There are some predefined error numbers in ANS Forth (see `errors.fs'). In Gforth (and most other systems) you can use the iors produced by various words as error numbers (e.g., a typical use of allocate is allocate throw). Gforth also provides the word exception to define your own error numbers (with decent error reporting); an ANS Forth version of this word (but without the error messages) is available in compat/except.fs. And finally, you can use your own error numbers (anything outside the range -4095..0), but won't get nice error messages, only numbers. For example, try:

 
-10 throw                    \ ANS defined
-267 throw                   \ system defined
s" my error" exception throw \ user defined
7 throw                      \ arbitrary number

doc--exception-exception

A common idiom to THROW a specific error if a flag is true is this:

 
( flag ) 0<> errno and throw

Your program can provide exception handlers to catch exceptions. An exception handler can be used to correct the problem, or to clean up some data structures and just throw the exception to the next exception handler. Note that throw jumps to the dynamically innermost exception handler. The system's exception handler is outermost, and just prints an error and restarts command-line interpretation (or, in batch mode (i.e., while processing the shell command line), leaves Gforth).

The ANS Forth way to catch exceptions is catch:

doc-catch

The most common use of exception handlers is to clean up the state when an error happens. E.g.,

 
base  >r hex \ actually the hex should be inside foo, or we h
['] foo catch ( nerror|0 )
r> base !
( nerror|0 ) throw \ pass it on

A use of catch for handling the error myerror might look like this:

 
['] foo catch
CASE
  myerror OF ... ( do something about it ) ENDOF
  dup throw \ default: pass other errors on, do nothing on non-errors
ENDCASE

Having to wrap the code into a separate word is often cumbersome, therefore Gforth provides an alternative syntax:

 
TRY
  code1
RECOVER     \ optional
  code2 \ optional
ENDTRY

This performs Code1. If code1 completes normally, execution continues after the endtry. If Code1 throws, the stacks are reset to the state during try, the throw value is pushed on the data stack, and execution constinues at code2, and finally falls through the endtry into the following code. If there is no recover clause, this works like an empty recover clause.

doc-try doc-recover doc-endtry

The cleanup example from above in this syntax:

 
base  >r TRY
  hex foo \ now the hex is placed correctly
  0       \ value for throw
ENDTRY
r> base ! throw

And here's the error handling example:

 
TRY
  foo
RECOVER
  CASE
    myerror OF ... ( do something about it ) ENDOF
    throw \ pass other errors on
  ENDCASE
ENDTRY

Programming style note: As usual, you should ensure that the stack depth is statically known at the end: either after the throw for passing on errors, or after the ENDTRY (or, if you use catch, after the end of the selection construct for handling the error).

There are two alternatives to throw: Abort" is conditional and you can provide an error message. Abort just produces an "Aborted" error.

The problem with these words is that exception handlers cannot differentiate between different abort"s; they just look like -2 throw to them (the error message cannot be accessed by standard programs). Similar abort looks like -1 throw to exception handlers.

doc-abort" doc-abort


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

  webmaster     delorie software   privacy  
  Copyright 2003   by The Free Software Foundation     Updated Jun 2003