## Exception handling

An exception is an object used to signal an error or other exceptional situation. The program or run-time system can throw the exception when an error is discovered. An exception handler is a program construct that registers an action to handle exceptions when the handler is active.

If an exception is thrown and not handled then the read-eval-print-loop will print a stack trace, and bring you back to the top level prompt. When not running interactively, an unhandled exception will normally cause Kawa to be exited.

In the Scheme exception model (as of R6RS and R7RS), exception handlers are one-argument procedures that determine the action the program takes when an exceptional situation is signaled. The system implicitly maintains a current exception handler in the dynamic environment. The program raises an exception by invoking the current exception handler, passing it an object encapsulating information about the exception. Any procedure accepting one argument can serve as an exception handler and any object can be used to represent an exception.

The Scheme exception model is implemented on top of the Java VM’s native exception model where the only objects that can be thrown are instances of `java.lang.Throwable`. Kawa also provides direct access to this native model, as well as older Scheme exception models.

Procedure: `with-exception-handler` `handler` `thunk`

> It is an error if `handler` does not accept one argument. It is also an error if `thunk` does not accept zero arguments. The `with-exception-handler` procedure returns the results of invoking `thunk`. The `handler` is installed as the current exception handler in the dynamic environment used for the invocation of `thunk`.

>     (call-with-current-continuation
>       (lambda (k)
>        (with-exception-handler
>         (lambda (x)
>          (display "condition: ")
>          (write x)
>          (newline)
>          (k 'exception))
>         (lambda ()
>          (+ 1 (raise ’an-error))))))
>            ⇒ exception
>            and prints condition: an-error

>     (with-exception-handler
>      (lambda (x)
>       (display "something went wrong\n"))
>      (lambda ()
>       (+ 1 (raise ’an-error))))
>         prints something went wrong

> After printing, the second example then raises another exception.

> Performance note: The `thunk` is inlined if it is a lambda expression. However, the `handler` cannot be inlined even if it is a lambda expression, because it could be called by `raise-continuable`. Using the `guard` form is usually more efficient.

Procedure: `raise` `obj`

> Raises an exception by invoking the current exception handler on `obj`. The handler is called with the same dynamic environment as that of the call to raise, except that the current exception handler is the one that was in place when the handler being called was installed. If the handler returns, then `obj` is re-raised in the same dynamic environment as the handler.

> If `obj` is an instance of `java.lang.Throwable`, then `raise` has the same effect as `primitive-throw`.

Procedure: `raise-continuable` `obj`

> Raises an exception by invoking the current exception handler on `obj`. The handler is called with the same dynamic environment as the call to `raise-continuable`, except that: (1) the current exception handler is the one that was in place when the handler being called was installed, and (2) if the handler being called returns, then it will again become the current exception handler. If the handler returns, the values it returns become the values returned by the call to `raise-continuable`.

>     (with-exception-handler
>       (lambda (con)
>         (cond
>           ((string? con)
>            (display con))
>           (else
>            (display "a warning has been issued")))
>         42)
>       (lambda ()
>         (+ (raise-continuable "should be a number")
>            23)))
>           prints: should be a number
>           ⇒ 65

Syntax: `guard` ``variable`` ``cond-clause```+` ``body``

> The `body` is evaluated with an exception handler that binds the raised object to `variable` and, within the scope of that binding, evaluates the clauses as if they were the clauses of a `cond` expression. That implicit `cond` expression is evaluated with the continuation and dynamic environment of the `guard` expression. If every cond-clause’s test evaluates to `#f` and there is no `else` clause, then `raise-continuable` is invoked on the raised object within the dynamic environment of the original call to `raise` or `raise-continuable`, except that the current exception handler is that of the `guard` expression.

>     (guard (condition
>              ((assq 'a condition) => cdr)
>              ((assq 'b condition)))
>       (raise (list (cons 'a 42))))
>           ⇒ 42

>     (guard (condition
>              ((assq 'a condition) => cdr)
>              ((assq 'b condition)))
>       (raise (list (cons 'b 23))))
>           ⇒ (b . 23)

> Performance note: Using `guard` is moderately efficient: there is some overhead compared to using native exception handling, but both the `body` and the handlers in the `cond-clause` are inlined.

Procedure: `dynamic-wind` `in-guard` `thunk` `out-guard`

> All three arguments must be 0-argument procedures. First calls `in-guard`, then `thunk`, then `out-guard`. The result of the expression is that of `thunk`. If `thunk` is exited abnormally (by throwing an exception or invoking a continuation), `out-guard` is called.

> If the continuation of the dynamic-wind is re-entered (which is not yet possible in Kawa), the `in-guard` is called again.

> This function was added in R5RS.

Procedure: `read-error?` `obj`

> Returns #t if `obj` is an object raised by the `read` procedure. (That is if `obj` is a `gnu.text.SyntaxException`.)

Procedure: `file-error?` `obj`

> Returns #t if `obj` is an object raised by inability to open an input or output port on a file. (This includes `java.io.FileNotFoundException` as well as certain other exceptions.)

### Simple error objects

Procedure: `error` `message` `obj` `...`

> Raises an exception as if by calling `raise` on a newly allocated simple error object, which encapsulates the information provided by `message` (which should a string), as well as any `obj` arguments, known as the irritants.

> The string representation of a simple error object is as if calling `(format "#<ERROR ~a~{ ~w~}>" `message` `irritants`)`. (That is the `message` is formatted as if with `display` while each irritant `obj` is formatted as if with `write`.)

> This procedure is part of SRFI-23, and R7RS. It differs from (and is incompatible with) R6RS’s `error` procedure.

Procedure: `error-object?` `obj`

> Returns `#t` if `obj` is a simple error object. Specifically, that `obj` is an instance of `kawa.lang.NamedException`. Otherwise, it returns `#f`.

Procedure: `error-object-message` `error-object`

> Returns the message encapsulated by error-object, which must be a simple error object.

Procedure: `error-object-irritants` `error-object`

> Returns a list of the irritants (other arguments) encapsulated by error-object, which must be a simple error object.

### Named exceptions

These functions associate a symbol with exceptions and handlers: A handler catches an exception if the symbol matches.

Procedure: `catch` `key` `thunk` `handler`

> Invoke `thunk` in the dynamic context of `handler` for exceptions matching `key`. If thunk throws to the symbol `key`, then `handler` is invoked this way:

>     (handler key args ...)

> `key` may be a symbol. The `thunk` takes no arguments. If `thunk` returns normally, that is the return value of `catch`.

> Handler is invoked outside the scope of its own `catch`. If `handler` again throws to the same key, a new handler from further up the call chain is invoked.

> If the key is `#t`, then a throw to any symbol will match this call to `catch`.

Procedure: `throw` `key` `arg` `...`

> Invoke the catch form matching `key`, passing the `arg`s to the current `handler`.

> If the key is a symbol it will match catches of the same symbol or of `#t`.

> If there is no handler at all, an error is signaled.

### Native exception handling

Procedure: `primitive-throw` `exception`

> Throws the `exception`, which must be an instance of a sub-class of `java.lang.Throwable`.

Syntax: `try-finally` `body` `handler`

> Evaluate `body`, and return its result. However, before it returns, evaluate `handler`. Even if `body` returns abnormally (by throwing an exception), `handler` is evaluated.

> (This is implemented just like Java’s `try`-`finally`. However, the current implementation does not duplicate the `handler`.)

Syntax: `try-catch` `body` `handler` `...`

> Evaluate `body`, in the context of the given `handler` specifications. Each `handler` has the form:

>     var type exp ...

> If an exception is thrown in `body`, the first `handler` is selected such that the thrown exception is an instance of the `handler`’s `type`. If no `handler` is selected, the exception is propagated through the dynamic execution context until a matching `handler` is found. (If no matching `handler` is found, then an error message is printed, and the computation terminated.)

> Once a `handler` is selected, the `var` is bound to the thrown exception, and the `exp` in the `handler` are executed. The result of the `try-catch` is the result of `body` if no exception is thrown, or the value of the last `exp` in the selected `handler` if an exception is thrown.

> (This is implemented just like Java’s `try`-`catch`.)