From posting-system@google.com Sun Nov 18 16:00:20 2001 Date: Sun, 18 Nov 2001 13:00:16 -0800 Reply-To: posting-system@google.com From: oleg@pobox.com (oleg@pobox.com) Newsgroups: comp.lang.scheme Subject: Resurrect exception handling SRFI (SRFI-12) Message-ID: <7eb8ac3e.0111181300.4e321932@posting.google.com> X-comment: more examples added. Status: OR This message announces complete native implementations of the exception handling SRFI (SRFI-12) on Gambit and Bigloo. Although SRFI-12 is officially withdrawn, it is still a well thought-out SRFI. By supporting it on different platforms, I can make my code more portable. Both Bigloo and Gambit implementations support the full SRFI-12, including continuable exceptions (signals), nested exceptions, and exceptional conditions. All examples given in SRFI-12 pass. Both implementations are 'native': a SRFI-12 application can capture, describe, and recover from native run-time exceptions, such as (/ 1 0) and (car '()). Native also means an ability to mix and match SRFI-12 and platform-specific exception-handling forms. The following are three illustrations of the degree of "nativity". The following code (handle-exceptions exn (begin (cerr "Went wrong: " ((condition-property-accessor 'exn 'message) exn) nl)) (car '())) when evaluated with Gambit 3.0, prints: Went wrong: (##signal.runtime-error ((PAIR expected car (())))) The same code evaluated by a Bigloo 2.4a interpreter, displays: Went wrong: (_car Type `pair' expected, `bnil' provided ()) The error messages look precise and informative. A Gambit application can use SRFI-12 exception-handling forms to capture an "Unbound-variable exception" in the interpreter. Therefore, it becomes possible to implement a form 'bound?', which tests if a given identifier corresponds to a bound variable: (define-macro (bound? var) `(bound-encap-var? (lambda () ,var))) (define (bound-encap-var? thunk) (handle-exceptions _ #f (thunk) #t)) (assert (bound? +)) ; identifier + is bound (let ((result (bound? xxx-+++-xxx))) ; and this identifier is not (assert (not result))) The Bigloo implementation of SRFI-12 permits arbitrary nesting of SRFI-12 and Bigloo's exception-handling forms. The following snippet from the validation code is a good example: (let ((result (bind-exit (escape) (with-exception-handler (lambda (exn) (if (equal? exn 1) (escape "Captured twice") (abort "Failure"))) (lambda () (try (/ 1 0) (lambda (escape proc msg obj) (abort 1)))))))) (assert (equal? result "Captured twice"))) Here, 'with-exception-handler' and 'abort' are defined in SRFI-12. The forms that you do not recognize are Bigloo-specific. The implementation of the exception-capture part of SRFI-12 was not easy, as evidenced by a fair to moderate amount of internal Gambit and Bigloo procedures. I had to rename SRFI-12 procedure 'signal' to 'exc:signal'. Otherwise the compiled Bigloo code that uses SRFI-12 crashes with a bus error (but not before the program fills its virtual space and swaps out all other processes). The reason is that Bigloo defines its own procedure 'signal', to capture UNIX signals. The implementation of exception conditions was taken from SRFI-12 reference implementation (after fixing a minor typo in that code). References SRFI-12: Exception Handling By William Clinger, R. Kent Dybvig, Matthew Flatt, and Marc Feeley http://srfi.schemers.org/srfi-12/ SRFI-12 Bigloo and Gambit implementation: procedures: http://pobox.com/~oleg/ftp/Scheme/util.html Gambit special forms (at the end of the following file): http://pobox.com/~oleg/ftp/Scheme/lib/myenv.scm Bigloo special forms: http://pobox.com/~oleg/ftp/Scheme/lib/myenv-bigloo.scm Validation code and the Makefile to run them: http://pobox.com/~oleg/ftp/Scheme/tests/ The Bigloo and Gambit implementations of SRFI-12 are in public domain and can be used for any suitable purpose. I have been using SRFI-12 for several months, in a code that implements two- and- three-tier Web services. The middle-tier uses exceptions to communicate CGI form parsing and type errors, and HTTP transaction failures. The middle-tier uses the same S-expression to generate web pages and SXML-RPC requests. Oops, that's a different topic.