On Scheme

Thoughts on Scheme and teaching Scheme

Exceptions

Posted by Peter on March 14, 2006

I know that there are exception handling libraries already developed for Scheme, but for fun, and because I want to develop an easy framework for beginners I am developing my own system. The problem with the existing systems is that they seem too complex (syntactically), and don’t look much like the error systems found in other languages. My goal is that the syntax should look something like this:

(try
    ; body statements
    …
    (thow exception-value) ; optional
  catch pred?
    ; body of exception
    ; can use err here to get at thrown value
    …
  catch (complicated-function err #t)
    …
  catch rest/else ; whatever, catches any uncaught exceptions
    …
  finally
    ; this body is called whenever the try finishes, but does not return values
    ; implemented using dynamic-wind)

It must also be possible for try statements to be nested, either in the main body or under a catch statement.

My current implementation (below) works as follows (and does handle nested trys):

(try
    ; body statements
    (throw exception-value)
  catch
    ; all thrown values caught here
    ; value can be accessed through err
)

My implementation is currently:

(define-syntax try
    (lambda (x)
      (letrec (
               (before-catch
                (lambda (x)
                  (cond ((null? x) '())
                        ((eq? (car x) 'catch) '())
                        (else (cons (car x) (before-catch (cdr x))))
                        )))
               (after-catch
                (lambda (x capt)
                  (cond ((null? x) '())
                        ((eq? (car x) 'catch) (after-catch (cdr x) #t))
                        ((not capt) (after-catch (cdr x) #f))
                        (else (cons (car x) (after-catch (cdr x) #t)))
                        )))
               (main-transformer
                (lambda (x)
                  (let (
                        (bc (before-catch x))
                        (ac (after-catch x #f))
                        )
                    (let (
                          (execbody (if (null? bc) '(begin (values)) `(begin ,@bc)))
                          (exceptbody (if (null? ac) '(begin (values)) `(begin ,@ac)))
                          )
                      `(call/cc
                        (lambda (outer)
                          (let
                              ((exception-handler (lambda (err)
                                                    ,exceptbody
                                                    )))
                            (exception-handler
                             (call/cc
                              (lambda (exception-entry)
                                (let ((throw exception-entry))
                                  (outer
                                   ,execbody
                                   )
                                  )
                                )))
                            )))
                      ))))
               )
       (datum->syntax-object x (main-transformer (cdr (syntax-object->datum x)))))))

Finally I want to add some sort of type hierarchy for exception values, so that if type X is a child of type Y then a catch Y? statement catches both X and Y type exceptions. If the system is good enough I may have throw auto-wrap the thrown value in a generic exception type if none is provided.

As always input is welcomed.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: