0.8.13.69:
[sbcl.git] / src / code / parse-defmacro.lisp
index dada4f5..af0c7ba 100644 (file)
 
 ;;; variables for accumulating the results of parsing a DEFMACRO. (Declarations
 ;;; in DEFMACRO are the reason this isn't as easy as it sounds.)
-(defvar *arg-tests* nil) ; tests that do argument counting at expansion time
+(defvar *arg-tests*) ; tests that do argument counting at expansion time
 (declaim (type list *arg-tests*))
-(defvar *system-lets* nil) ; LET bindings done to allow lambda-list parsing
+(defvar *system-lets*) ; LET bindings done to allow lambda-list parsing
 (declaim (type list *system-lets*))
-(defvar *user-lets* nil) ; LET bindings that the user has explicitly supplied
+(defvar *user-lets*) ; LET bindings that the user has explicitly supplied
 (declaim (type list *user-lets*))
-(defvar *env-var* nil) ; &ENVIRONMENT variable name
+(defvar *env-var*) ; &ENVIRONMENT variable name
 
 ;; the default default for unsupplied &OPTIONAL and &KEY args
-(defvar *default-default* nil)
+(defvar *default-default*)
 
 ;;; temps that we introduce and might not reference
 (defvar *ignorable-vars*)
 (declaim (type list *ignorable-vars*))
 
-;;; Return, as multiple values, a body, possibly a declare form to put
+;;; Return, as multiple values, a body, possibly a DECLARE form to put
 ;;; where this code is inserted, the documentation for the parsed
 ;;; body, and bounds on the number of arguments.
 (defun parse-defmacro (lambda-list arg-list-name body name error-kind
                                   (doc-string-allowed t)
                                   ((:environment env-arg-name))
                                   ((:default-default *default-default*))
-                                  (error-fun 'error))
+                                  (error-fun 'error)
+                                   (wrap-block t))
   (multiple-value-bind (forms declarations documentation)
-      (parse-body body doc-string-allowed)
+      (parse-body body :doc-string-allowed doc-string-allowed)
     (let ((*arg-tests* ())
          (*user-lets* ())
          (*system-lets* ())
                   ,@*arg-tests*
                   (let* ,(nreverse *user-lets*)
                     ,@declarations
-                    ,@forms))
+                     ,@(if wrap-block
+                           `((block ,(fun-name-block-name name)
+                               ,@forms))
+                           forms)))
                `(,@(when (and env-arg-name (not env-arg-used))
                       `((declare (ignore ,env-arg-name)))))
                documentation
@@ -87,6 +91,7 @@
         (maximum 0)
         (minimum 0)
         (keys ())
+        (key-seen nil)
         ;; ANSI specifies that dotted lists are "treated exactly as if the
         ;; parameter name that ends the list had appeared preceded by &rest."
         ;; We force this behavior by transforming dotted lists into ordinary
        ((null rest-of-args))
       (macrolet ((process-sublist (var sublist-name path)
                    (once-only ((var var))
-                     `(if (consp ,var)
+                     `(if (listp ,var)
                           (let ((sub-list-name (gensym ,sublist-name)))
                             (push-sub-list-binding sub-list-name ,path ,var
                                                    name error-kind error-fun)
                 (setq rest-name (gensym "KEYWORDS-"))
                 (push rest-name *ignorable-vars*)
                 (setq restp t)
+               (setq key-seen t)
                 (push-let-binding rest-name path t))
                (&allow-other-keys
                 (setq allow-other-keys-p t))
                                    :minimum ,minimum
                                    :maximum ,explicit-maximum)))
               *arg-tests*))
-      (when keys
+      (when key-seen
        (let ((problem (gensym "KEY-PROBLEM-"))
              (info (gensym "INFO-")))
          (push `(multiple-value-bind (,problem ,info)