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.