- (let ((normal-return (make-symbol "normal-return"))
- (error-return (make-symbol "error-return")))
- `(block ,error-return
- (multiple-value-call (lambda ,@(cdr no-error-clause))
- (block ,normal-return
- (return-from ,error-return
- (handler-case (return-from ,normal-return ,form)
- ,@(remove no-error-clause cases)))))))
- (let ((tag (gensym))
- (var (gensym))
- (annotated-cases (mapcar (lambda (case) (cons (gensym) case))
- cases)))
- `(block ,tag
- (let ((,var nil))
- (declare (ignorable ,var))
- (tagbody
- (handler-bind
- ,(mapcar (lambda (annotated-case)
- (list (cadr annotated-case)
- `(lambda (temp)
- ,(if (caddr annotated-case)
- `(setq ,var temp)
- '(declare (ignore temp)))
- (go ,(car annotated-case)))))
- annotated-cases)
- (return-from ,tag
- #!-x86 ,form
- #!+x86 (multiple-value-prog1 ,form
- ;; Need to catch FP errors here!
- (float-wait))))
- ,@(mapcan
- (lambda (annotated-case)
- (list (car annotated-case)
- (let ((body (cdddr annotated-case)))
- `(return-from
- ,tag
- ,(cond ((caddr annotated-case)
- `(let ((,(caaddr annotated-case)
- ,var))
- ,@body))
- (t
- `(locally ,@body)))))))
- annotated-cases))))))))
+ (let ((normal-return (make-symbol "normal-return"))
+ (error-return (make-symbol "error-return")))
+ `(block ,error-return
+ (multiple-value-call (lambda ,@(cdr no-error-clause))
+ (block ,normal-return
+ (return-from ,error-return
+ (handler-case (return-from ,normal-return ,form)
+ ,@(remove no-error-clause cases)))))))
+ (let* ((local-funs nil)
+ (annotated-cases
+ (mapcar (lambda (case)
+ (with-unique-names (tag fun)
+ (destructuring-bind (type ll &body body) case
+ (push `(,fun ,ll ,@body) local-funs)
+ (list tag type ll fun))))
+ cases)))
+ (with-unique-names (block cell form-fun)
+ `(dx-flet ((,form-fun ()
+ #!-x86 ,form
+ ;; Need to catch FP errors here!
+ #!+x86 (multiple-value-prog1 ,form (float-wait)))
+ ,@(reverse local-funs))
+ (declare (optimize (sb!c::check-tag-existence 0)))
+ (block ,block
+ ;; KLUDGE: We use a dx CONS cell instead of just assigning to
+ ;; the variable directly, so that we can stack allocate
+ ;; robustly: dx value cells don't work quite right, and it is
+ ;; possible to construct user code that should loop
+ ;; indefinitely, but instead eats up some stack each time
+ ;; around.
+ (dx-let ((,cell (cons :condition nil)))
+ (declare (ignorable ,cell))
+ (tagbody
+ (%handler-bind
+ ,(mapcar (lambda (annotated-case)
+ (destructuring-bind (tag type ll fun-name) annotated-case
+ (declare (ignore fun-name))
+ (list type
+ `(lambda (temp)
+ ,(if ll
+ `(setf (cdr ,cell) temp)
+ '(declare (ignore temp)))
+ (go ,tag)))))
+ annotated-cases)
+ (return-from ,block (,form-fun)))
+ ,@(mapcan
+ (lambda (annotated-case)
+ (destructuring-bind (tag type ll fun-name) annotated-case
+ (declare (ignore type))
+ (list tag
+ `(return-from ,block
+ ,(if ll
+ `(,fun-name (cdr ,cell))
+ `(,fun-name))))))
+ annotated-cases))))))))))