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.