On this page:
«error-handling»

6 Exceptions

There are as many error handling strategies as programming languages, ranging from “drop everything and quit” to “don’t have errors.”

Here’s a simple one: if an error occurs, put it on the stack and call the function current-error-handler. If that’s not defined, the interpreter has no choice but to quit altogether.

All the pieces are already in place: interp-call, defined in Core operations, is already set up to use interp-try-eval.

; Custom error type that can be put on the stack in its component parts
(struct builtin-failure exn:fail
  ([name : Symbol] [irritants : (Listof Any)])
  #:transparent
  #:type-name Builtin-Failure)
 
; Utility for builtins to signal an error
(: interp-error (All (A) ((Symbol) #:rest Any . ->* . A)))
(define (interp-error name . irritants)
  (raise (builtin-failure
           "Builtin failure"
           (current-continuation-marks)
           name irritants)))
 
(: interp-handle-error (Context Stack Symbol (Listof Any)
                                . -> . (Values Context Stack)))
(define (interp-handle-error ctx stack name irritants)
  (if (context-resolve ctx 'current-error-handler)
    ; Put the error on the stack
    (interp-call ctx
                 (list* name irritants stack)
                 'current-error-handler)
    ; Kill the interpreter if current-error-handler isn't defined
    (apply error "Unhandled error" name irritants)))
 
(: interp-try-eval (Context Stack Symbol Function
                            . -> . (Values Context Stack)))
(define (interp-try-eval ctx stack name f)
  (with-handlers
    ; Builtin failures get the arguments given to interp-error
    ([builtin-failure?
       (lambda ([e : Builtin-Failure])
         (interp-handle-error ctx stack
                              (builtin-failure-name e)
                              (cons name (builtin-failure-irritants e))))]
     [exn:fail? ; should this catch all exceptions, including breaks?
       (lambda ([e : exn])
         ; Try to deal with this error in a reasonable way
         (interp-handle-error ctx stack
                              name
                              (list (exn-message e))))])
    (interp-eval ctx stack f)))
 
; TODO tests for this.