* lisp/emacs-lisp/cl-lib.el: Set more meaningful version number.
[bpt/emacs.git] / lisp / emacs-lisp / cl-macs.el
index 95aa1f1..c0b6be4 100644 (file)
 
 ;;; Initialization.
 
+;; Place compiler macros at the beginning, otherwise uses of the corresponding
+;; functions can lead to recursive-loads that prevent the calls from
+;; being optimized.
+
+;;;###autoload
+(defun cl--compiler-macro-list* (_form arg &rest others)
+  (let* ((args (reverse (cons arg others)))
+        (form (car args)))
+    (while (setq args (cdr args))
+      (setq form `(cons ,(car args) ,form)))
+    form))
+
+;;;###autoload
+(defun cl--compiler-macro-cXXr (form x)
+  (let* ((head (car form))
+         (n (symbol-name (car form)))
+         (i (- (length n) 2)))
+    (if (not (string-match "c[ad]+r\\'" n))
+        (if (and (fboundp head) (symbolp (symbol-function head)))
+            (cl--compiler-macro-cXXr (cons (symbol-function head) (cdr form))
+                                     x)
+          (error "Compiler macro for cXXr applied to non-cXXr form"))
+      (while (> i (match-beginning 0))
+        (setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
+        (setq i (1- i)))
+      x)))
+
 ;;; Some predicates for analyzing Lisp forms.
 ;; These are used by various
 ;; macro expanders to optimize the results in certain common cases.
@@ -366,9 +393,14 @@ its argument list allows full Common Lisp conventions."
       (mapcar (lambda (x)
                 (cond
                  ((symbolp x)
-                  (if (eq ?\& (aref (symbol-name x) 0))
-                      (setq state x)
-                    (make-symbol (upcase (symbol-name x)))))
+                  (let ((first (aref (symbol-name x) 0)))
+                    (if (eq ?\& first)
+                        (setq state x)
+                      ;; Strip a leading underscore, since it only
+                      ;; means that this argument is unused.
+                      (make-symbol (upcase (if (eq ?_ first)
+                                               (substring (symbol-name x) 1)
+                                             (symbol-name x)))))))
                  ((not (consp x)) x)
                  ((memq state '(nil &rest)) (cl--make-usage-args x))
                  (t      ;(VAR INITFORM SVAR) or ((KEYWORD VAR) INITFORM SVAR).
@@ -452,7 +484,13 @@ its argument list allows full Common Lisp conventions."
          (let ((arg (pop args)))
            (or (consp arg) (setq arg (list arg)))
            (let* ((karg (if (consp (car arg)) (caar arg)
-                          (intern (format ":%s" (car arg)))))
+                           (let ((name (symbol-name (car arg))))
+                             ;; Strip a leading underscore, since it only
+                             ;; means that this argument is unused, but
+                             ;; shouldn't affect the key's name (bug#12367).
+                             (if (eq ?_ (aref name 0))
+                                 (setq name (substring name 1)))
+                             (intern (format ":%s" name)))))
                   (varg (if (consp (car arg)) (cl-cadar arg) (car arg)))
                   (def (if (cdr arg) (cadr arg)
                          (or (car cl--bind-defs) (cadr (assq varg cl--bind-defs)))))
@@ -516,6 +554,7 @@ its argument list allows full Common Lisp conventions."
 
 ;;;###autoload
 (defmacro cl-destructuring-bind (args expr &rest body)
+  "Bind the variables in ARGS to the result of EXPR and execute BODY."
   (declare (indent 2)
            (debug (&define cl-macro-list def-form cl-declarations def-body)))
   (let* ((cl--bind-lets nil) (cl--bind-forms nil) (cl--bind-inits nil)
@@ -717,7 +756,7 @@ This is compatible with Common Lisp, but note that `defun' and
 
 ;;;###autoload
 (defmacro cl-loop (&rest loop-args)
-  "The Common Lisp `cl-loop' macro.
+  "The Common Lisp `loop' macro.
 Valid clauses are:
   for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM,
   for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR,
@@ -731,7 +770,21 @@ Valid clauses are:
   finally return EXPR, named NAME.
 
 \(fn CLAUSE...)"
-  (declare (debug (&rest &or symbolp form)))
+  (declare (debug (&rest &or
+                         ;; These are usually followed by a symbol, but it can
+                         ;; actually be any destructuring-bind pattern, which
+                         ;; would erroneously match `form'.
+                         [[&or "for" "as" "with" "and"] sexp]
+                         ;; These are followed by expressions which could
+                         ;; erroneously match `symbolp'.
+                         [[&or "from" "upfrom" "downfrom" "to" "upto" "downto"
+                               "above" "below" "by" "in" "on" "=" "across"
+                               "repeat" "while" "until" "always" "never"
+                               "thereis" "collect" "append" "nconc" "sum"
+                               "count" "maximize" "minimize" "if" "unless"
+                               "return"] form]
+                         ;; Simple default, which covers 99% of the cases.
+                         symbolp form)))
   (if (not (memq t (mapcar 'symbolp (delq nil (delq t (cl-copy-list loop-args))))))
       `(cl-block nil (while t ,@loop-args))
     (let ((cl--loop-args loop-args) (cl--loop-name nil) (cl--loop-bindings nil)
@@ -1207,8 +1260,9 @@ Valid clauses are:
                        loop-for-steps)))
 
               (t
+               ;; This is an advertised interface: (info "(cl)Other Clauses").
                (let ((handler (and (symbolp word)
-                                   (get word 'cl--loop-for-handler))))
+                                   (get word 'cl-loop-for-handler))))
                  (if handler
                      (funcall handler var)
                    (error "Expected a `for' preposition, found %s" word)))))
@@ -1355,7 +1409,8 @@ Valid clauses are:
                    ,cl--loop-finish-flag nil) cl--loop-body))
 
      (t
-      (let ((handler (and (symbolp word) (get word 'cl--loop-handler))))
+      ;; This is an advertised interface: (info "(cl)Other Clauses").
+      (let ((handler (and (symbolp word) (get word 'cl-loop-handler))))
        (or handler (error "Expected a cl-loop keyword, found %s" word))
        (funcall handler))))
     (if (eq (car cl--loop-args) 'and)
@@ -1411,8 +1466,15 @@ Valid clauses are:
          cl--loop-accum-var))))
 
 (defun cl--loop-build-ands (clauses)
+  "Return various representations of (and . CLAUSES).
+CLAUSES is a list of Elisp expressions, where clauses of the form
+\(progn E1 E2 E3 .. t) are the focus of particular optimizations.
+The return value has shape (COND BODY COMBO)
+such that COMBO is equivalent to (and . CLAUSES)."
   (let ((ands nil)
        (body nil))
+    ;; Look through `clauses', trying to optimize (progn ,@A t) (progn ,@B) ,@C
+    ;; into (progn ,@A ,@B) ,@C.
     (while clauses
       (if (and (eq (car-safe (car clauses)) 'progn)
               (eq (car (last (car clauses))) t))
@@ -1423,6 +1485,7 @@ Valid clauses are:
                                             (cl-cdadr clauses)
                                           (list (cadr clauses))))
                                  (cddr clauses)))
+            ;; A final (progn ,@A t) is moved outside of the `and'.
            (setq body (cdr (butlast (pop clauses)))))
        (push (pop clauses) ands)))
     (setq ands (or (nreverse ands) (list t)))
@@ -1438,7 +1501,7 @@ Valid clauses are:
 
 ;;;###autoload
 (defmacro cl-do (steps endtest &rest body)
-  "The Common Lisp `cl-do' loop.
+  "The Common Lisp `do' loop.
 
 \(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
   (declare (indent 2)
@@ -1450,7 +1513,7 @@ Valid clauses are:
 
 ;;;###autoload
 (defmacro cl-do* (steps endtest &rest body)
-  "The Common Lisp `cl-do*' loop.
+  "The Common Lisp `do*' loop.
 
 \(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
   (declare (indent 2) (debug cl-do))
@@ -1519,6 +1582,9 @@ from OBARRAY.
 
 ;;;###autoload
 (defmacro cl-do-all-symbols (spec &rest body)
+  "Like `cl-do-symbols', but use the default obarray.
+
+\(fn (VAR [RESULT]) BODY...)"
   (declare (indent 1) (debug ((symbolp &optional form) cl-declarations body)))
   `(cl-do-symbols (,(car spec) nil ,(cadr spec)) ,@body))
 
@@ -1543,7 +1609,7 @@ before assigning any symbols SYM to the corresponding values.
   "Bind SYMBOLS to VALUES dynamically in BODY.
 The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists.
 Each symbol in the first list is bound to the corresponding value in the
-second list (or made unbound if VALUES is shorter than SYMBOLS); then the
+second list (or to nil if VALUES is shorter than SYMBOLS); then the
 BODY forms are executed and their result is returned.  This is much like
 a `let' form, except that the list of symbols can be computed at run-time."
   (declare (indent 2) (debug (form form body)))
@@ -1582,7 +1648,7 @@ a `let' form, except that the list of symbols can be computed at run-time."
 
 ;;;###autoload
 (defmacro cl-flet (bindings &rest body)
-  "Make temporary function definitions.
+  "Make local function definitions.
 Like `cl-labels' but the definitions are not recursive.
 
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
@@ -1606,7 +1672,7 @@ Like `cl-labels' but the definitions are not recursive.
 
 ;;;###autoload
 (defmacro cl-flet* (bindings &rest body)
-  "Make temporary function definitions.
+  "Make local function definitions.
 Like `cl-flet' but the definitions can refer to previous ones.
 
 \(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
@@ -1821,10 +1887,12 @@ values.  For compatibility, (cl-values A B C) is a synonym for (list A B C).
 
 ;;;###autoload
 (defmacro cl-locally (&rest body)
+  "Equivalent to `progn'."
   (declare (debug t))
   (cons 'progn body))
 ;;;###autoload
 (defmacro cl-the (_type form)
+  "At present this ignores _TYPE and is simply equivalent to FORM."
   (declare (indent 1) (debug (cl-type-spec form)))
   form)
 
@@ -1891,8 +1959,6 @@ See Info node `(cl)Declarations' for details."
        (cl-do-proclaim (pop specs) nil)))
   nil)
 
-
-
 ;;; The standard modify macros.
 
 ;; `setf' is now part of core Elisp, defined in gv.el.
@@ -1915,7 +1981,7 @@ before assigning any PLACEs to the corresponding values.
       (or p (error "Odd number of arguments to cl-psetf"))
       (pop p))
     (if simple
-       `(progn (setf ,@args) nil)
+       `(progn (setq ,@args) nil)
       (setq args (reverse args))
       (let ((expr `(setf ,(cadr args) ,(car args))))
        (while (setq args (cddr args))
@@ -2096,8 +2162,9 @@ copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'.
 You can use the accessors to set the corresponding slots, via `setf'.
 
 NAME may instead take the form (NAME OPTIONS...), where each
-OPTION is either a single keyword or (KEYWORD VALUE).
-See Info node `(cl)Structures' for a list of valid keywords.
+OPTION is either a single keyword or (KEYWORD VALUE) where
+KEYWORD can be one of :conc-name, :constructor, :copier, :predicate,
+:type, :named, :initial-offset, :print-function, or :include.
 
 Each SLOT may instead take the form (SLOT SLOT-OPTS...), where
 SLOT-OPTS are keyword-value pairs for that slot.  Currently, only
@@ -2105,7 +2172,7 @@ one keyword is supported, `:read-only'.  If this has a non-nil
 value, that slot cannot be set via `setf'.
 
 \(fn NAME SLOTS...)"
-  (declare (doc-string 2)
+  (declare (doc-string 2) (indent 1)
            (debug
             (&define                    ;Makes top-level form not be wrapped.
              [&or symbolp
@@ -2265,26 +2332,29 @@ value, that slot cannot be set via `setf'.
                           (if (= pos 0) '(car cl-x)
                             `(nth ,pos cl-x)))) forms)
              (push (cons accessor t) side-eff)
-              ;; Don't bother defining a setf-expander, since gv-get can use
-              ;; the compiler macro to get the same result.
-              ;;(push `(gv-define-setter ,accessor (cl-val cl-x)
-              ;;         ,(if (cadr (memq :read-only (cddr desc)))
-              ;;              `(progn (ignore cl-x cl-val)
-              ;;                      (error "%s is a read-only slot"
-              ;;                             ',accessor))
-              ;;            ;; If cl is loaded only for compilation,
-              ;;            ;; the call to cl--struct-setf-expander would
-              ;;            ;; cause a warning because it may not be
-              ;;            ;; defined at run time.  Suppress that warning.
-              ;;            `(progn
-              ;;               (declare-function
-              ;;                cl--struct-setf-expander "cl-macs"
-              ;;                (x name accessor pred-form pos))
-              ;;               (cl--struct-setf-expander
-              ;;                cl-val cl-x ',name ',accessor
-              ;;                ,(and pred-check `',pred-check)
-              ;;                ,pos))))
-              ;;      forms)
+              (if (cadr (memq :read-only (cddr desc)))
+                  (push `(gv-define-expander ,accessor
+                           (lambda (_cl-do _cl-x)
+                             (error "%s is a read-only slot" ',accessor)))
+                        forms)
+                ;; For normal slots, we don't need to define a setf-expander,
+                ;; since gv-get can use the compiler macro to get the
+                ;; same result.
+                ;; (push `(gv-define-setter ,accessor (cl-val cl-x)
+                ;;          ;; If cl is loaded only for compilation,
+                ;;          ;; the call to cl--struct-setf-expander would
+                ;;          ;; cause a warning because it may not be
+                ;;          ;; defined at run time.  Suppress that warning.
+                ;;          (progn
+                ;;            (declare-function
+                ;;             cl--struct-setf-expander "cl-macs"
+                ;;             (x name accessor pred-form pos))
+                ;;            (cl--struct-setf-expander
+                ;;             cl-val cl-x ',name ',accessor
+                ;;             ,(and pred-check `',pred-check)
+                ;;             ,pos)))
+                ;;       forms)
+                )
              (if print-auto
                  (nconc print-func
                         (list `(princ ,(format " %s" slot) cl-s)
@@ -2470,6 +2540,10 @@ and then returning foo."
 
 ;;;###autoload
 (defun cl-compiler-macroexpand (form)
+  "Like `macroexpand', but for compiler macros.
+Expands FORM repeatedly until no further expansion is possible.
+Returns FORM unchanged if it has no compiler macro, or if it has a
+macro that returns its `&whole' argument."
   (while
       (let ((func (car-safe form)) (handler nil))
        (while (and (symbolp func)
@@ -2583,14 +2657,6 @@ surrounded by (cl-block NAME ...).
       `(if (cl-member ,a ,list ,@keys) ,list (cons ,a ,list))
     form))
 
-;;;###autoload
-(defun cl--compiler-macro-list* (_form arg &rest others)
-  (let* ((args (reverse (cons arg others)))
-        (form (car args)))
-    (while (setq args (cdr args))
-      (setq form `(cons ,(car args) ,form)))
-    form))
-
 (defun cl--compiler-macro-get (_form sym prop &optional def)
   (if def
       `(cl-getf (symbol-plist ,sym) ,prop ,def)
@@ -2602,21 +2668,6 @@ surrounded by (cl-block NAME ...).
         (cl--make-type-test temp (cl--const-expr-val type)))
     form))
 
-;;;###autoload
-(defun cl--compiler-macro-cXXr (form x)
-  (let* ((head (car form))
-         (n (symbol-name (car form)))
-         (i (- (length n) 2)))
-    (if (not (string-match "c[ad]+r\\'" n))
-        (if (and (fboundp head) (symbolp (symbol-function head)))
-            (cl--compiler-macro-cXXr (cons (symbol-function head) (cdr form))
-                                     x)
-          (error "Compiler macro for cXXr applied to non-cXXr form"))
-      (while (> i (match-beginning 0))
-        (setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
-        (setq i (1- i)))
-      x)))
-
 (dolist (y '(cl-first cl-second cl-third cl-fourth
              cl-fifth cl-sixth cl-seventh
              cl-eighth cl-ninth cl-tenth
@@ -2651,7 +2702,6 @@ surrounded by (cl-block NAME ...).
 
 ;; Local variables:
 ;; byte-compile-dynamic: t
-;; byte-compile-warnings: (not cl-functions)
 ;; generated-autoload-file: "cl-loaddefs.el"
 ;; End: