;;; SRFI-34: Exceptions for scheme ;;; This file contains the macros. srfi-34-support.scm contains ;;; some support procedures needed at runtime. ;;; This is the reference implementation copied (almost) verbatim from ;;; http://srfi.schemers.org/srfi-34/srfi-34.html with rearranging and ;;; slight modifications to be a chicken egg. (module srfi-34 (*current-exception-handlers* with-exception-handlers with-exception-handler raise guard) (import (except chicken with-exception-handler) scheme) (define *current-exception-handlers* (list (lambda (condition) (error "unhandled exception" condition)))) (define (with-exception-handlers new-handlers thunk) (let ((previous-handlers *current-exception-handlers*)) (dynamic-wind (lambda () (set! *current-exception-handlers* new-handlers)) thunk (lambda () (set! *current-exception-handlers* previous-handlers))))) (define (with-exception-handler handler thunk) (with-exception-handlers (cons handler *current-exception-handlers*) thunk)) (define (raise obj) (let ((handlers *current-exception-handlers*)) (with-exception-handlers (cdr handlers) (lambda () ((car handlers) obj) (error "handler returned" (car handlers) obj))))) ;(require-extension ports) (define-syntax guard (syntax-rules () ((guard (var clause ...) e1 e2 ...) ((call-with-current-continuation (lambda (guard-k) (with-exception-handler (lambda (condition) ((call-with-current-continuation (lambda (handler-k) (guard-k (lambda () (let ((var condition)) ; clauses may SET! var (guard-aux (handler-k (lambda () (raise condition))) clause ...)))))))) (lambda () (call-with-values (lambda () e1 e2 ...) (lambda args (guard-k (lambda () (apply values args))))))))))))) (define-syntax guard-aux (syntax-rules (else =>) ((guard-aux reraise (else result1 result2 ...)) (begin result1 result2 ...)) ((guard-aux reraise (test => result)) (let ((temp test)) (if temp (result temp) reraise))) ((guard-aux reraise (test => result) clause1 clause2 ...) (let ((temp test)) (if temp (result temp) (guard-aux reraise clause1 clause2 ...)))) ((guard-aux reraise (test)) test) ((guard-aux reraise (test) clause1 clause2 ...) (let ((temp test)) (if temp temp (guard-aux reraise clause1 clause2 ...)))) ((guard-aux reraise (test result1 result2 ...)) (if test (begin result1 result2 ...) reraise)) ((guard-aux reraise (test result1 result2 ...) clause1 clause2 ...) (if test (begin result1 result2 ...) (guard-aux reraise clause1 clause2 ...))))) )