#23 error function doesn't use *error-hook*

open
nobody
None
5
2011-08-20
2011-08-20
Doug Currie
No

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

Discussion

  • Doug Currie
    Doug Currie
    2011-08-27

    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)