The error function seems to bypass use of *error-hook* -- perhaps(?) that makes sense, but error needs to unwind the handler stack.
ts> *handlers*
()
ts> (catch 'baz (error "msg e"))
Error: msg e
ts> *handlers*
(#<CLOSURE>)
ts> (sin 5.0)
baz
ts>
Would dynamic-wind help in the implementation of catch to make sure the handler stack is unwound?
Should the uses of error in the code be changed to use *error-hook*? E.g., string->anyatom anyatom->string quasiquote
Here is a suggested fix:
@@ -536,35 +549,45 @@
;
; If used outside a (catch ...), reverts to (error "message)
-(define *handlers* (list))
-(define (push-handler proc)
- (set! *handlers* (cons proc *handlers*)))
+;;Guarded because we must only eval this once, because doing so
+;;redefines error
+;;
+(unless (defined? 'error-toplevel)
-(define (pop-handler)
- (let ((h (car *handlers*)))
- (set! *handlers* (cdr *handlers*))
- h))
+ (define *handlers* (list))
-(define (more-handlers?)
- (pair? *handlers*))
+ (define (push-handler proc)
+ (set! *handlers* (cons proc *handlers*)))
-(define (throw . x)
- (if (more-handlers?)
- (apply (pop-handler))
- (apply error x)))
+ (define (pop-handler)
+ (let ((h (car *handlers*)))
+ (set! *handlers* (cdr *handlers*))
+ h))
-(macro (catch form)
- (let ((label (gensym)))
- `(call/cc (lambda (exit)
- (push-handler (lambda () (exit ,(cadr form))))
- (let ((,label (begin ,@(cddr form))))
- (pop-handler)
- ,label)))))
+ (define (more-handlers?)
+ (pair? *handlers*))
-(define *error-hook* throw)
+ (define error-toplevel error)
+ (define (throw . x)
+ (if (more-handlers?)
+ (apply (pop-handler))
+ (apply error-toplevel x)))
+ (macro (catch form)
+ (let ((label (gensym)))
+ `(call/cc (lambda (exit)
+ (push-handler (lambda () (exit ,(cadr form))))
+ (let ((,label (begin ,@(cddr form))))
+ (pop-handler)
+ ,label)))))
+
+ (define *error-hook* throw)
+
+ (define (error . x) (apply (or *error-hook* error-toplevel) x))
+)
+
;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL
(macro (make-environment form)