~ chicken-r7rs (master) 9569944c5b71dd2a476f72ee24dce17d3a3ab87c


commit 9569944c5b71dd2a476f72ee24dce17d3a3ab87c
Author:     Evan Hanson <evhan@foldling.org>
AuthorDate: Thu May 30 08:43:45 2013 +0000
Commit:     Evan Hanson <evhan@foldling.org>
CommitDate: Thu May 30 08:43:45 2013 +0000

    First cut at exception semantics

diff --git a/r7rs.scm b/r7rs.scm
index 583817c..ae86f7b 100644
--- a/r7rs.scm
+++ b/r7rs.scm
@@ -1,7 +1,10 @@
 (module r7rs
 
 (
+ ;; Exception handling
+ guard
  ;; Exceptions
+ with-exception-handler
  raise
  raise-continuable
  error-object?
@@ -9,7 +12,6 @@
  error-object-irritants
  read-error?
  file-error?
- ; TODO guard
  ;; System interface
  command-line
  exit
@@ -37,12 +39,108 @@
              #t)
             (else (old-hook char port))))))
 
+;;;
+;;; 4.2.7. Exception handling
+;;;
+
+;; guard & guard-aux copied verbatim from the draft.
+(define-syntax guard
+  (syntax-rules ()
+    ((guard (var clause ...) e1 e2 ...)
+     ((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 ()
+             (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 ...)))))
+
 ;;;
 ;;; 6.11. Exceptions
 ;;;
 
-(define raise abort)
-(define raise-continuable signal)
+(define-values (with-exception-handler raise raise-continuable)
+  (let ((exception-handlers
+         (let ((lst (list ##sys#current-exception-handler)))
+           (set-cdr! lst lst)
+           lst)))
+    (values
+     ;; with-exception-handler
+     (lambda (handler thunk)
+       (dynamic-wind
+        (lambda ()
+          (set! exception-handlers (cons handler exception-handlers))
+          (set! ##sys#current-exception-handler handler))
+        thunk
+        (lambda ()
+          (set! exception-handlers (cdr exception-handlers))
+          (set! ##sys#current-exception-handler (car exception-handlers)))))
+     ;; raise
+     (lambda (obj)
+       (with-exception-handler
+        (cadr exception-handlers)
+        (lambda ()
+          ((cadr exception-handlers) obj)
+          ((car exception-handlers)
+           (make-property-condition
+            'exn
+            'message "exception handler returned"
+            'arguments '()
+            'location #f)))))
+     ;; raise-continuable
+     (lambda (obj)
+       (with-exception-handler
+        (cadr exception-handlers)
+        (lambda ()
+          ((cadr exception-handlers) obj)))))))
+
 (define error-object? condition?)
 (define error-object-message (condition-property-accessor 'exn 'message))
 (define error-object-irritants (condition-property-accessor 'exn 'arguments))
Trap