~ chicken-r7rs (master) 8e3cd329195c5dd4853ca93d641808f903f17b8b


commit 8e3cd329195c5dd4853ca93d641808f903f17b8b
Author:     Peter Bex <peter@more-magic.net>
AuthorDate: Thu Jun 13 19:14:25 2013 +0000
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Thu Jun 13 19:14:25 2013 +0000

    Fix with-exception-handler and guard; improve tests a bit

diff --git a/scheme.base.scm b/scheme.base.scm
index d6166c6..b2c2b90 100644
--- a/scheme.base.scm
+++ b/scheme.base.scm
@@ -37,69 +37,70 @@
 ;;;
 
 ;; guard & guard-aux copied verbatim from the draft.
+;; guard-aux put in a letrec-syntax due to import/export issues...
 (define-syntax guard
   (syntax-rules ()
     ((guard (var clause ...) e1 e2 ...)
-     ((call/cc
+     (letrec-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))
+                         (or test reraise))
+                        ((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 ___))))))
+      ((call/cc
         (lambda (guard-k)
           (with-exception-handler
            (lambda (condition)
              ((call/cc
-                (lambda (handler-k)
-                  (guard-k
-                   (lambda ()
-                     (let ((var condition))
-                       (guard-aux
-                        (handler-k
-                         (lambda ()
-                           (raise-continuable condition)))
-                        clause ...))))))))
+               (lambda (handler-k)
+                 (guard-k
+                  (lambda ()
+                    (let ((var condition))
+                      (guard-aux
+                       (handler-k
+                        (lambda ()
+                          (raise-continuable 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))
-     (or test reraise))
-    ((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 ...)))))
+                 (lambda () e1 e2 ...)
+               (lambda args
+                 (guard-k
+                  (lambda ()
+                    (apply values args))))))))))))))
 
 
 ;;;
 ;;; 6.11. Exceptions
 ;;;
 
+;; XXX TODO: This is not threadsafe!
 (define-values (with-exception-handler raise raise-continuable)
   (let ((exception-handlers
          (let ((lst (list ##sys#current-exception-handler)))
@@ -110,6 +111,11 @@
      (lambda (handler thunk)
        (dynamic-wind
         (lambda ()
+          ;; We might be interoperating with srfi-12 handlers set by intermediate
+          ;; non-R7RS code, so check if a new handler was set in the meanwhile.
+          (unless (eq? (car exception-handlers) ##sys#current-exception-handler)
+            (set! exception-handlers
+              (cons ##sys#current-exception-handler exception-handlers)))
           (set! exception-handlers (cons handler exception-handlers))
           (set! ##sys#current-exception-handler handler))
         thunk
diff --git a/tests/run.scm b/tests/run.scm
index a79a9c7..9201b30 100644
--- a/tests/run.scm
+++ b/tests/run.scm
@@ -3,6 +3,8 @@
 (define (read-from-string s)
   (with-input-from-string s read))
 
+(test-begin "r7rs tests")
+
 (test-group "long boolean literals"
  (test #t (read-from-string "#t"))
  (test #f (read-from-string "#f"))
@@ -28,13 +30,16 @@
                (lambda () (+ 1 (raise 'an-error)))))
   (test-error "with-exception-handler (raise)"
               (with-exception-handler
-               (lambda (e) 'ignore)
+               (lambda (e) (raise 'another-error))
                (lambda () (+ 1 (raise 'an-error)))))
   (test "with-exception-handler (raise-continuable)"
-        65
-        (with-exception-handler
-         (lambda (e) 42)
-         (lambda () (+ (raise-continuable "should be a number") 23))))
+        '("should be a number" 65)
+        (let* ((exception-object #f)
+               (return-value 
+                (with-exception-handler
+                 (lambda (e) (set! exception-object e) 42)
+                 (lambda () (+ (raise-continuable "should be a number") 23)))))
+          (list exception-object return-value)))
   (test "error-object? (#f)" #f (error-object? 'no))
   (test "error-object? (#t)" #t (error-object? (catch (car '()))))
   (test "error-object-message" "fubar" (error-object-message (catch (error "fubar"))))
@@ -110,3 +115,7 @@
                    (not (input-port-open? the-string-port)))
       (test-assert "It's ok to close input ports that are already closed"
                    (close-port the-string-port)))))
+
+(test-end "r7rs tests")
+
+(test-exit)
Trap