[Bug-openmcl] reworked typecase patch

bryan o'connor bryan-openmcl at lunch.org
Tue Dec 14 16:11:33 MST 2004


typecase was always pushing the t clause (if present) to the end of
the clauses.  i suspect that most cases when it appears before the
end, the user intended for it to be equivalent to a final OTHERWISE
clause.  hopefully the warning messages about later clauses being
shadowed will be sufficient to alert them.  as an added benefit it
dead-code strips any cases following a t-clause.

finally it now correctly raises an error if OTHERWISE (if present)
is not the final clause.

? (typecase 3
	(t 'correct)
	(number 'wrong))
; Warning: Clause (NUMBER 'WRONG) ignored in TYPECASE form - shadowed 
by (T 'CORRECT) .
; While executing: CCL::TYPECASE-AUX
CORRECT

? (macroexpand-1 '(typecase 3 (t 'correct) (number 'wrong)))
[...]
(LET ((#:G1 3)) (DECLARE (IGNORABLE #:G1)) (COND ((TYPEP #:G1 'T) NIL 
'CORRECT)))

? (typecase 3 (otherwise 'wrong) (number 'correct))
 > Error in process listener(1): OTHERWISE must be final clause in 
TYPECASE form.
 > While executing: CCL::TYPECASE-AUX


	...bryan


-------------- next part --------------
Index: lib/macros.lisp
===================================================================
RCS file: /usr/local/tmpcvs/ccl-0.14-dev/ccl/lib/macros.lisp,v
retrieving revision 1.20
diff -c -r1.20 macros.lisp
*** lib/macros.lisp	25 Sep 2004 21:36:06 -0000	1.20
--- lib/macros.lisp	14 Dec 2004 22:49:39 -0000
***************
*** 785,824 ****
  (defun typecase-aux (key-var clauses &optional e-c-p keyform)
    (let* ((construct (if e-c-p (if (eq e-c-p 'etypecase) e-c-p 'ctypecase) 'typecase))
           (types ())
!          (t-clause ())
!          (body ()))
      (flet ((bad-clause (c) 
               (error "Invalid clause ~S in ~S form." c construct)))
        (dolist (clause clauses)
          (if (atom clause)
!           (bad-clause clause)
!           (destructuring-bind (typespec &body consequents) clause
!             (when (eq construct 'typecase)
!               (if (eq typespec 'otherwise)
!                 (setq typespec t))
!               (if (eq typespec t)
!                 (if t-clause
!                   (bad-clause clause)   ; seen one already
!                   (setq t-clause `( t nil , at consequents)))))
!             (unless (and (eq construct 'typecase)
!                          (eq typespec t))
!               (when
!                   (dolist (already types t)
!                     (when (subtypep typespec already)
!                       (warn "Clause ~S ignored in ~S form - shadowed by ~S ." clause construct (assq already clauses))
!                       (return)))
!                 (push typespec types)
!                 (unless (eq typespec t)
!                   (setq typespec `(typep ,key-var ',typespec)))
!                 (push `(,typespec nil , at consequents) body))))))
        (when e-c-p
          (setq types `(or ,@(nreverse types)))
          (if (eq construct 'etypecase)
!           (push `(t (values (%err-disp #.$XWRONGTYPE ,key-var ',types))) body)
!           (push `(t (setf ,keyform (ensure-value-of-type ,key-var ',types ',keyform))
!                   (go ,e-c-p)) body))))
!     (when t-clause
!       (push t-clause body))
      `(cond ,@(nreverse body))))
  
  (defmacro typecase (keyform &body clauses)
--- 785,818 ----
  (defun typecase-aux (key-var clauses &optional e-c-p keyform)
    (let* ((construct (if e-c-p (if (eq e-c-p 'etypecase) e-c-p 'ctypecase) 'typecase))
           (types ())
!          (body ())
!          otherwise-seen-p)
      (flet ((bad-clause (c) 
               (error "Invalid clause ~S in ~S form." c construct)))
        (dolist (clause clauses)
          (if (atom clause)
!             (bad-clause clause))
!         (if otherwise-seen-p
!             (error "OTHERWISE must be final clause in ~S form." construct))
!         (destructuring-bind (typespec &body consequents) clause
!           (when (eq construct 'typecase)
!             (if (eq typespec 'otherwise)
!                 (progn (setq typespec t)
!                        (setq otherwise-seen-p t))))
!           (when
!               (dolist (already types t)
!                 (when (subtypep typespec already)
!                   (warn "Clause ~S ignored in ~S form - shadowed by ~S ." clause construct (assq already clauses))
!                   (return))))
!           (push typespec types)
!           (setq typespec `(typep ,key-var ',typespec))
!           (push `(,typespec nil , at consequents) body)))
        (when e-c-p
          (setq types `(or ,@(nreverse types)))
          (if (eq construct 'etypecase)
!             (push `(t (values (%err-disp #.$XWRONGTYPE ,key-var ',types))) body)
!             (push `(t (setf ,keyform (ensure-value-of-type ,key-var ',types ',keyform))
!                       (go ,e-c-p)) body))))
      `(cond ,@(nreverse body))))
  
  (defmacro typecase (keyform &body clauses)
-------------- next part --------------




More information about the Bug-openmcl mailing list