Raymond Toy pushed to branch master at cmucl / cmucl

Commits:

3 changed files:

Changes:

  • src/bootfiles/20f/boot-2015-06-1.lisp
    --- /dev/null
    +++ b/src/bootfiles/20f/boot-2015-06-1.lisp
    @@ -0,0 +1,156 @@
    +;; Fix #6.
    +;;
    +;; Use this to bootstrap the change using the snapshot-2015-06 binary.
    +(in-package "KERNEL")
    +(export '(invalid-case))
    +(in-package "CONDITIONS")
    +
    +(ext:without-package-locks
    +(define-condition invalid-case (reference-condition error)
    +  ((name :initarg :name
    +	 :reader invalid-case-name)
    +   (format :initarg :format-control
    +	   :reader invalid-case-format)
    +   (args :initarg :format-arguments
    +	 :reader invalid-case-format-args))
    +  (:report (lambda (condition stream)
    +	     (format stream "~A: " (invalid-case-name condition))
    +	     (apply #'format stream (invalid-case-format condition) (invalid-case-format-args condition))
    +	     (print-references (reference-condition-references condition) stream))))
    +)
    +
    +(in-package "LISP")
    +
    +(ext:without-package-locks 
    +(defun case-body (name keyform cases multi-p test proceedp &optional allow-otherwise)
    +  (let ((keyform-value (gensym))
    +	(clauses ())
    +	(keys ()))
    +    (do* ((case-list cases (cdr case-list))
    +	  (case (first case-list) (first case-list)))
    +	 ((null case-list))
    +      (cond ((atom case)
    +	     (error (intl:gettext "~S -- Bad clause in ~S.") case name))
    +	    ((and (not allow-otherwise)
    +		  (memq (car case) '(t otherwise)))
    +	     (cond ((null (cdr case-list))
    +		    ;; The CLHS says OTHERWISE clause is an OTHERWISE clause
    +		    ;; only if it's the last case.  Otherwise, it's just a
    +		    ;; normal clause.
    +		    (push `(t nil ,@(rest case)) clauses))
    +		   ((and (eq name 'case))
    +		    (let ((key (first case)))
    +		      (error 'kernel:invalid-case
    +			     :name name
    +			     :format-control (intl:gettext
    +					      "~<~A is a key designator only in the final otherwise-clause. ~
    +                                              Use (~A) to use it as a normal-clause or move the clause to the ~
    +                                              correct position.~:@>")
    +			     :format-arguments (list (list key key))
    +			     :references (list '(:ansi-cl :section (5 3))
    +					       (list :ansi-cl :macro name)))))
    +		   ((eq (first case) t)
    +		    ;; The key T is normal clause, because it's not
    +		    ;; the last clause.
    +		    (push (first case) keys)
    +		    (push `((,test ,keyform-value
    +			    ',(first case)) nil ,@(rest case)) clauses))))
    +	    ((and multi-p (listp (first case)))
    +	     (setf keys (append (first case) keys))
    +	     (push `((or ,@(mapcar #'(lambda (key)
    +				       `(,test ,keyform-value ',key))
    +				   (first case)))
    +		     nil ,@(rest case))
    +		   clauses))
    +	    (t
    +	     (when (and allow-otherwise
    +			(memq (car case) '(t otherwise)))
    +	       (warn 'kernel:simple-style-warning
    +		     :format-control (intl:gettext "Bad style to use ~S in ~S")
    +		     :format-arguments (list (car case) name)))
    +	     (push (first case) keys)
    +	     (push `((,test ,keyform-value
    +			    ',(first case)) nil ,@(rest case)) clauses))))
    +    (case-body-aux name keyform keyform-value clauses keys proceedp
    +		   allow-otherwise
    +		   `(,(if multi-p 'member 'or) ,@keys))))
    +
    +;;; CASE-BODY-AUX provides the expansion once CASE-BODY has groveled all the
    +;;; cases.  Note: it is not necessary that the resulting code signal
    +;;; case-failure conditions, but that's what KMP's prototype code did.  We call
    +;;; CASE-BODY-ERROR, because of how closures are compiled.  RESTART-CASE has
    +;;; forms with closures that the compiler causes to be generated at the top of
    +;;; any function using the case macros, regardless of whether they are needed.
    +;;;
    +(defun case-body-aux (name keyform keyform-value clauses keys
    +		      proceedp allow-otherwise expected-type)
    +  (if proceedp
    +      (let ((block (gensym))
    +	    (again (gensym)))
    +	`(let ((,keyform-value ,keyform))
    +	   (block ,block
    +	     (tagbody
    +	      ,again
    +	      (return-from
    +	       ,block
    +	       (cond ,@(nreverse clauses)
    +		     (t
    +		      (setf ,keyform-value
    +			    (setf ,keyform
    +				  (case-body-error
    +				   ',name ',keyform ,keyform-value
    +				   ',expected-type ',keys)))
    +		      (go ,again))))))))
    +      `(let ((,keyform-value ,keyform))
    +	 ,keyform-value ; prevent warnings when key not used eg (case key (t))
    +	 (cond
    +	  ,@(nreverse clauses)
    +	  ,@(if allow-otherwise
    +		`((t (error 'conditions::case-failure
    +			    :name ',name
    +			    :datum ,keyform-value
    +			    :expected-type ',expected-type
    +			    :possibilities ',keys))))))))
    +
    +(defmacro case (keyform &body cases)
    +  "CASE Keyform {({(Key*) | Key} Form*)}*
    +  Evaluates the Forms in the first clause with a Key EQL to the value
    +  of Keyform.  If a singleton key is T or Otherwise then the clause is
    +  a default clause."
    +  (case-body 'case keyform cases t 'eql nil))
    +
    +(defmacro ccase (keyform &body cases)
    +  "CCASE Keyform {({(Key*) | Key} Form*)}*
    +  Evaluates the Forms in the first clause with a Key EQL to the value of
    +  Keyform.  If none of the keys matches then a correctable error is
    +  signalled."
    +  (case-body 'ccase keyform cases t 'eql t t))
    +
    +(defmacro ecase (keyform &body cases)
    +  "ECASE Keyform {({(Key*) | Key} Form*)}*
    +  Evaluates the Forms in the first clause with a Key EQL to the value of
    +  Keyform.  If none of the keys matches then an error is signalled."
    +  (case-body 'ecase keyform cases t 'eql nil t))
    +
    +(defmacro typecase (keyform &body cases)
    +  "TYPECASE Keyform {(Type Form*)}*
    +  Evaluates the Forms in the first clause for which TYPEP of Keyform
    +  and Type is true.  If a singleton key is T or Otherwise then the
    +  clause is a default clause."
    +  (case-body 'typecase keyform cases nil 'typep nil))
    +
    +(defmacro ctypecase (keyform &body cases)
    +  "CTYPECASE Keyform {(Type Form*)}*
    +  Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
    +  is true.  If no form is satisfied then a correctable error is signalled."
    +  (case-body 'ctypecase keyform cases nil 'typep t t))
    +
    +(defmacro etypecase (keyform &body cases)
    +  "ETYPECASE Keyform {(Type Form*)}*
    +  Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
    +  is true.  If no form is satisfied then an error is signalled."
    +  (case-body 'etypecase keyform cases nil 'typep nil t))
    +
    +
    +)
    +
    

  • src/code/macros.lisp
    --- a/src/code/macros.lisp
    +++ b/src/code/macros.lisp
    @@ -1347,7 +1347,7 @@
     ;;; generate an ERROR form.  (This is for CCASE and ECASE which allow
     ;;; using T and OTHERWISE as regular keys.)
     ;;;
    -(defun case-body (name keyform cases multi-p test errorp proceedp &optional allow-otherwise)
    +(defun case-body (name keyform cases multi-p test proceedp &optional allow-otherwise)
       (let ((keyform-value (gensym))
     	(clauses ())
     	(keys ()))
    @@ -1362,9 +1362,7 @@
     		    ;; The CLHS says OTHERWISE clause is an OTHERWISE clause
     		    ;; only if it's the last case.  Otherwise, it's just a
     		    ;; normal clause.
    -		    (if errorp
    -			(error (intl:gettext "No default clause allowed in ~S: ~S") name case)
    -			(push `(t nil ,@(rest case)) clauses)))
    +		    (push `(t nil ,@(rest case)) clauses))
     		   ((and (eq name 'case))
     		    (let ((key (first case)))
     		      (error 'kernel:invalid-case
    @@ -1398,7 +1396,7 @@
     	     (push (first case) keys)
     	     (push `((,test ,keyform-value
     			    ',(first case)) nil ,@(rest case)) clauses))))
    -    (case-body-aux name keyform keyform-value clauses keys errorp proceedp
    +    (case-body-aux name keyform keyform-value clauses keys proceedp
     		   allow-otherwise
     		   `(,(if multi-p 'member 'or) ,@keys))))
     
    @@ -1410,7 +1408,7 @@
     ;;; any function using the case macros, regardless of whether they are needed.
     ;;;
     (defun case-body-aux (name keyform keyform-value clauses keys
    -		      errorp proceedp allow-otherwise expected-type)
    +		      proceedp allow-otherwise expected-type)
       (if proceedp
           (let ((block (gensym))
     	    (again (gensym)))
    @@ -1432,7 +1430,7 @@
     	 ,keyform-value ; prevent warnings when key not used eg (case key (t))
     	 (cond
     	  ,@(nreverse clauses)
    -	  ,@(if (or errorp allow-otherwise)
    +	  ,@(if allow-otherwise
     		`((t (error 'conditions::case-failure
     			    :name ',name
     			    :datum ,keyform-value
    @@ -1460,39 +1458,39 @@
       Evaluates the Forms in the first clause with a Key EQL to the value
       of Keyform.  If a singleton key is T or Otherwise then the clause is
       a default clause."
    -  (case-body 'case keyform cases t 'eql nil nil))
    +  (case-body 'case keyform cases t 'eql nil))
     
     (defmacro ccase (keyform &body cases)
       "CCASE Keyform {({(Key*) | Key} Form*)}*
       Evaluates the Forms in the first clause with a Key EQL to the value of
       Keyform.  If none of the keys matches then a correctable error is
       signalled."
    -  (case-body 'ccase keyform cases t 'eql nil t t))
    +  (case-body 'ccase keyform cases t 'eql t t))
     
     (defmacro ecase (keyform &body cases)
       "ECASE Keyform {({(Key*) | Key} Form*)}*
       Evaluates the Forms in the first clause with a Key EQL to the value of
       Keyform.  If none of the keys matches then an error is signalled."
    -  (case-body 'ecase keyform cases t 'eql nil nil t))
    +  (case-body 'ecase keyform cases t 'eql nil t))
     
     (defmacro typecase (keyform &body cases)
       "TYPECASE Keyform {(Type Form*)}*
       Evaluates the Forms in the first clause for which TYPEP of Keyform
       and Type is true.  If a singleton key is T or Otherwise then the
       clause is a default clause."
    -  (case-body 'typecase keyform cases nil 'typep nil nil))
    +  (case-body 'typecase keyform cases nil 'typep nil))
     
     (defmacro ctypecase (keyform &body cases)
       "CTYPECASE Keyform {(Type Form*)}*
       Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
       is true.  If no form is satisfied then a correctable error is signalled."
    -  (case-body 'ctypecase keyform cases nil 'typep nil t t))
    +  (case-body 'ctypecase keyform cases nil 'typep t t))
     
     (defmacro etypecase (keyform &body cases)
       "ETYPECASE Keyform {(Type Form*)}*
       Evaluates the Forms in the first clause for which TYPEP of Keyform and Type
       is true.  If no form is satisfied then an error is signalled."
    -  (case-body 'etypecase keyform cases nil 'typep nil nil t))
    +  (case-body 'etypecase keyform cases nil 'typep nil t))
     
     
     ;;;; ASSERT and CHECK-TYPE.
    

  • src/i18n/locale/cmucl.pot
    --- a/src/i18n/locale/cmucl.pot
    +++ b/src/i18n/locale/cmucl.pot
    @@ -14689,10 +14689,6 @@ msgid "~S -- Bad clause in ~S."
     msgstr ""
     
     #: src/code/macros.lisp
    -msgid "No default clause allowed in ~S: ~S"
    -msgstr ""
    -
    -#: src/code/macros.lisp
     msgid ""
     "~<~A is a key designator only in the final otherwise-clause. ~\n"
     "                                              Use (~A) to use it as a "