Provide generalized variables in core Elisp.
[bpt/emacs.git] / lisp / emacs-lisp / cl-macs.el
CommitLineData
d9857e53 1;;; cl-macs.el --- Common Lisp macros -*- lexical-binding: t; coding: utf-8 -*-
fcd73769 2
acaf905b 3;; Copyright (C) 1993, 2001-2012 Free Software Foundation, Inc.
fcd73769
RS
4
5;; Author: Dave Gillespie <daveg@synaptics.com>
6;; Version: 2.02
7;; Keywords: extensions
bd78fa1d 8;; Package: emacs
fcd73769
RS
9
10;; This file is part of GNU Emacs.
11
d6cba7ae 12;; GNU Emacs is free software: you can redistribute it and/or modify
fcd73769 13;; it under the terms of the GNU General Public License as published by
d6cba7ae
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
fcd73769
RS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
d6cba7ae 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
fcd73769 24
07b3798c 25;;; Commentary:
fcd73769
RS
26
27;; These are extensions to Emacs Lisp that provide a degree of
28;; Common Lisp compatibility, beyond what is already built-in
29;; in Emacs Lisp.
30;;
31;; This package was written by Dave Gillespie; it is a complete
32;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
33;;
fcd73769
RS
34;; Bug reports, comments, and suggestions are welcome!
35
36;; This file contains the portions of the Common Lisp extensions
37;; package which should be autoloaded, but need only be present
38;; if the compiler or interpreter is used---this file is not
39;; necessary for executing compiled code.
40
41;; See cl.el for Change Log.
42
43
07b3798c 44;;; Code:
fcd73769 45
7c1898a7 46(require 'cl-lib)
4dd1c416 47(require 'macroexp)
2ee3d7f0
SM
48;; `gv' is required here because cl-macs can be loaded before loaddefs.el.
49(require 'gv)
fcd73769 50
fcd73769 51(defmacro cl-pop2 (place)
7c1898a7 52 (declare (debug edebug-sexps))
03fef3e6
SM
53 `(prog1 (car (cdr ,place))
54 (setq ,place (cdr (cdr ,place)))))
fcd73769 55
fcd73769
RS
56(defvar cl-optimize-safety)
57(defvar cl-optimize-speed)
58
fcd73769
RS
59;;; Initialization.
60
4dd1c416
SM
61;;; Some predicates for analyzing Lisp forms.
62;; These are used by various
63;; macro expanders to optimize the results in certain common cases.
fcd73769 64
4dd1c416 65(defconst cl--simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max
b7b95a1e 66 car-safe cdr-safe progn prog1 prog2))
4dd1c416 67(defconst cl--safe-funcs '(* / % length memq list vector vectorp
b7b95a1e
DL
68 < > <= >= = error))
69
4dd1c416
SM
70(defun cl--simple-expr-p (x &optional size)
71 "Check if no side effects, and executes quickly."
b7b95a1e 72 (or size (setq size 10))
7c1898a7 73 (if (and (consp x) (not (memq (car x) '(quote function cl-function))))
b7b95a1e 74 (and (symbolp (car x))
4dd1c416 75 (or (memq (car x) cl--simple-funcs)
b7b95a1e
DL
76 (get (car x) 'side-effect-free))
77 (progn
78 (setq size (1- size))
79 (while (and (setq x (cdr x))
4dd1c416 80 (setq size (cl--simple-expr-p (car x) size))))
b7b95a1e
DL
81 (and (null x) (>= size 0) size)))
82 (and (> size 0) (1- size))))
83
4dd1c416
SM
84(defun cl--simple-exprs-p (xs)
85 (while (and xs (cl--simple-expr-p (car xs)))
b7b95a1e
DL
86 (setq xs (cdr xs)))
87 (not xs))
88
4dd1c416
SM
89(defun cl--safe-expr-p (x)
90 "Check if no side effects."
7c1898a7 91 (or (not (and (consp x) (not (memq (car x) '(quote function cl-function)))))
b7b95a1e 92 (and (symbolp (car x))
4dd1c416
SM
93 (or (memq (car x) cl--simple-funcs)
94 (memq (car x) cl--safe-funcs)
b7b95a1e
DL
95 (get (car x) 'side-effect-free))
96 (progn
4dd1c416 97 (while (and (setq x (cdr x)) (cl--safe-expr-p (car x))))
b7b95a1e
DL
98 (null x)))))
99
100;;; Check if constant (i.e., no side effects or dependencies).
4dd1c416 101(defun cl--const-expr-p (x)
b7b95a1e
DL
102 (cond ((consp x)
103 (or (eq (car x) 'quote)
7c1898a7 104 (and (memq (car x) '(function cl-function))
b7b95a1e
DL
105 (or (symbolp (nth 1 x))
106 (and (eq (car-safe (nth 1 x)) 'lambda) 'func)))))
107 ((symbolp x) (and (memq x '(nil t)) t))
108 (t t)))
109
4dd1c416
SM
110(defun cl--const-expr-val (x)
111 (and (macroexp-const-p x) (if (consp x) (nth 1 x) x)))
b7b95a1e
DL
112
113(defun cl-expr-access-order (x v)
e754e83b
SM
114 ;; This apparently tries to return nil iff the expression X evaluates
115 ;; the variables V in the same order as they appear in V (so as to
116 ;; be able to replace those vars with the expressions they're bound
117 ;; to).
118 ;; FIXME: This is very naive, it doesn't even check to see if those
119 ;; variables appear more than once.
4dd1c416 120 (if (macroexp-const-p x) v
b7b95a1e
DL
121 (if (consp x)
122 (progn
123 (while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v)))
124 v)
125 (if (eq x (car v)) (cdr v) '(t)))))
126
4dd1c416
SM
127(defun cl--expr-contains (x y)
128 "Count number of times X refers to Y. Return nil for 0 times."
7c1898a7 129 ;; FIXME: This is naive, and it will cl-count Y as referred twice in
e129292c
CS
130 ;; (let ((Y 1)) Y) even though it should be 0. Also it is often called on
131 ;; non-macroexpanded code, so it may also miss some occurrences that would
132 ;; only appear in the expanded code.
b7b95a1e 133 (cond ((equal y x) 1)
7c1898a7 134 ((and (consp x) (not (memq (car x) '(quote function cl-function))))
b7b95a1e 135 (let ((sum 0))
e129292c 136 (while (consp x)
4dd1c416
SM
137 (setq sum (+ sum (or (cl--expr-contains (pop x) y) 0))))
138 (setq sum (+ sum (or (cl--expr-contains x y) 0)))
b7b95a1e
DL
139 (and (> sum 0) sum)))
140 (t nil)))
141
4dd1c416
SM
142(defun cl--expr-contains-any (x y)
143 (while (and y (not (cl--expr-contains x (car y)))) (pop y))
b7b95a1e
DL
144 y)
145
4dd1c416
SM
146(defun cl--expr-depends-p (x y)
147 "Check whether X may depend on any of the symbols in Y."
148 (and (not (macroexp-const-p x))
149 (or (not (cl--safe-expr-p x)) (cl--expr-contains-any x y))))
b7b95a1e 150
fcd73769
RS
151;;; Symbols.
152
4735906a 153(defvar cl--gensym-counter)
ebacfcc6 154;;;###autoload
7c1898a7 155(defun cl-gensym (&optional prefix)
fcd73769
RS
156 "Generate a new uninterned symbol.
157The name is made by appending a number to PREFIX, default \"G\"."
a766dfa1
JB
158 (let ((pfix (if (stringp prefix) prefix "G"))
159 (num (if (integerp prefix) prefix
4735906a
SM
160 (prog1 cl--gensym-counter
161 (setq cl--gensym-counter (1+ cl--gensym-counter))))))
a766dfa1 162 (make-symbol (format "%s%d" pfix num))))
fcd73769 163
ebacfcc6 164;;;###autoload
7c1898a7 165(defun cl-gentemp (&optional prefix)
fcd73769
RS
166 "Generate a new interned symbol with a unique name.
167The name is made by appending a number to PREFIX, default \"G\"."
a766dfa1 168 (let ((pfix (if (stringp prefix) prefix "G"))
fcd73769 169 name)
4735906a
SM
170 (while (intern-soft (setq name (format "%s%d" pfix cl--gensym-counter)))
171 (setq cl--gensym-counter (1+ cl--gensym-counter)))
fcd73769
RS
172 (intern name)))
173
174
175;;; Program structure.
176
b1198e17 177(def-edebug-spec cl-declarations
7c1898a7 178 (&rest ("cl-declare" &rest sexp)))
b1198e17
SM
179
180(def-edebug-spec cl-declarations-or-string
181 (&or stringp cl-declarations))
182
183(def-edebug-spec cl-lambda-list
184 (([&rest arg]
185 [&optional ["&optional" cl-&optional-arg &rest cl-&optional-arg]]
186 [&optional ["&rest" arg]]
187 [&optional ["&key" [cl-&key-arg &rest cl-&key-arg]
188 &optional "&allow-other-keys"]]
189 [&optional ["&aux" &rest
190 &or (symbolp &optional def-form) symbolp]]
191 )))
192
193(def-edebug-spec cl-&optional-arg
194 (&or (arg &optional def-form arg) arg))
195
196(def-edebug-spec cl-&key-arg
197 (&or ([&or (symbolp arg) arg] &optional def-form arg) arg))
198
bb3faf5b
SM
199(defconst cl--lambda-list-keywords
200 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
201
202(defvar cl--bind-block) (defvar cl--bind-defs) (defvar cl--bind-enquote)
203(defvar cl--bind-inits) (defvar cl--bind-lets) (defvar cl--bind-forms)
204
205(defun cl--transform-lambda (form bind-block)
206 (let* ((args (car form)) (body (cdr form)) (orig-args args)
207 (cl--bind-block bind-block) (cl--bind-defs nil) (cl--bind-enquote nil)
208 (cl--bind-inits nil) (cl--bind-lets nil) (cl--bind-forms nil)
209 (header nil) (simple-args nil))
210 (while (or (stringp (car body))
211 (memq (car-safe (car body)) '(interactive cl-declare)))
212 (push (pop body) header))
213 (setq args (if (listp args) (cl-copy-list args) (list '&rest args)))
214 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
215 (if (setq cl--bind-defs (cadr (memq '&cl-defs args)))
216 (setq args (delq '&cl-defs (delq cl--bind-defs args))
217 cl--bind-defs (cadr cl--bind-defs)))
218 (if (setq cl--bind-enquote (memq '&cl-quote args))
219 (setq args (delq '&cl-quote args)))
220 (if (memq '&whole args) (error "&whole not currently implemented"))
221 (let* ((p (memq '&environment args)) (v (cadr p))
222 (env-exp 'macroexpand-all-environment))
223 (if p (setq args (nconc (delq (car p) (delq v args))
224 (list '&aux (list v env-exp))))))
225 (while (and args (symbolp (car args))
226 (not (memq (car args) '(nil &rest &body &key &aux)))
227 (not (and (eq (car args) '&optional)
228 (or cl--bind-defs (consp (cadr args))))))
229 (push (pop args) simple-args))
230 (or (eq cl--bind-block 'cl-none)
231 (setq body (list `(cl-block ,cl--bind-block ,@body))))
232 (if (null args)
233 (cl-list* nil (nreverse simple-args) (nconc (nreverse header) body))
234 (if (memq '&optional simple-args) (push '&optional args))
235 (cl--do-arglist args nil (- (length simple-args)
236 (if (memq '&optional simple-args) 1 0)))
237 (setq cl--bind-lets (nreverse cl--bind-lets))
238 (cl-list* (and cl--bind-inits `(cl-eval-when (compile load eval)
239 ,@(nreverse cl--bind-inits)))
240 (nconc (nreverse simple-args)
241 (list '&rest (car (pop cl--bind-lets))))
242 (nconc (let ((hdr (nreverse header)))
243 ;; Macro expansion can take place in the middle of
244 ;; apparently harmless computation, so it should not
245 ;; touch the match-data.
246 (save-match-data
247 (require 'help-fns)
248 (cons (help-add-fundoc-usage
249 (if (stringp (car hdr)) (pop hdr))
250 (format "%S"
251 (cons 'fn
252 (cl--make-usage-args orig-args))))
253 hdr)))
254 (list `(let* ,cl--bind-lets
255 ,@(nreverse cl--bind-forms)
256 ,@body)))))))
257
ebacfcc6 258;;;###autoload
7c1898a7 259(defmacro cl-defun (name args &rest body)
69d8fb1e 260 "Define NAME as a function.
fcd73769 261Like normal `defun', except ARGLIST allows full Common Lisp conventions,
7c1898a7 262and BODY is implicitly surrounded by (cl-block NAME ...).
69d8fb1e
SM
263
264\(fn NAME ARGLIST [DOCSTRING] BODY...)"
b1198e17
SM
265 (declare (debug
266 ;; Same as defun but use cl-lambda-list.
2ee3d7f0 267 (&define [&or name ("setf" :name setf name)]
b1198e17
SM
268 cl-lambda-list
269 cl-declarations-or-string
270 [&optional ("interactive" interactive)]
70b8ef8f 271 def-body))
b581bb5c 272 (doc-string 3)
70b8ef8f 273 (indent 2))
4dd1c416 274 (let* ((res (cl--transform-lambda (cons args body) name))
03fef3e6
SM
275 (form `(defun ,name ,@(cdr res))))
276 (if (car res) `(progn ,(car res) ,form) form)))
fcd73769 277
b1198e17
SM
278;; The lambda list for macros is different from that of normal lambdas.
279;; Note that &environment is only allowed as first or last items in the
280;; top level list.
281
282(def-edebug-spec cl-macro-list
283 (([&optional "&environment" arg]
284 [&rest cl-macro-arg]
285 [&optional ["&optional" &rest
286 &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
287 [&optional [[&or "&rest" "&body"] cl-macro-arg]]
288 [&optional ["&key" [&rest
289 [&or ([&or (symbolp cl-macro-arg) arg]
290 &optional def-form cl-macro-arg)
291 arg]]
292 &optional "&allow-other-keys"]]
293 [&optional ["&aux" &rest
294 &or (symbolp &optional def-form) symbolp]]
295 [&optional "&environment" arg]
296 )))
297
298(def-edebug-spec cl-macro-arg
299 (&or arg cl-macro-list1))
300
301(def-edebug-spec cl-macro-list1
302 (([&optional "&whole" arg] ;; only allowed at lower levels
303 [&rest cl-macro-arg]
304 [&optional ["&optional" &rest
305 &or (cl-macro-arg &optional def-form cl-macro-arg) arg]]
306 [&optional [[&or "&rest" "&body"] cl-macro-arg]]
307 [&optional ["&key" [&rest
308 [&or ([&or (symbolp cl-macro-arg) arg]
309 &optional def-form cl-macro-arg)
310 arg]]
311 &optional "&allow-other-keys"]]
312 [&optional ["&aux" &rest
313 &or (symbolp &optional def-form) symbolp]]
314 . [&or arg nil])))
315
ebacfcc6 316;;;###autoload
7c1898a7 317(defmacro cl-defmacro (name args &rest body)
69d8fb1e 318 "Define NAME as a macro.
fcd73769 319Like normal `defmacro', except ARGLIST allows full Common Lisp conventions,
7c1898a7 320and BODY is implicitly surrounded by (cl-block NAME ...).
69d8fb1e
SM
321
322\(fn NAME ARGLIST [DOCSTRING] BODY...)"
b1198e17 323 (declare (debug
70b8ef8f 324 (&define name cl-macro-list cl-declarations-or-string def-body))
b581bb5c 325 (doc-string 3)
70b8ef8f 326 (indent 2))
4dd1c416 327 (let* ((res (cl--transform-lambda (cons args body) name))
03fef3e6
SM
328 (form `(defmacro ,name ,@(cdr res))))
329 (if (car res) `(progn ,(car res) ,form) form)))
fcd73769 330
b1198e17
SM
331(def-edebug-spec cl-lambda-expr
332 (&define ("lambda" cl-lambda-list
333 ;;cl-declarations-or-string
334 ;;[&optional ("interactive" interactive)]
335 def-body)))
336
7c1898a7 337;; Redefine function-form to also match cl-function
b1198e17
SM
338(def-edebug-spec function-form
339 ;; form at the end could also handle "function",
340 ;; but recognize it specially to avoid wrapping function forms.
341 (&or ([&or "quote" "function"] &or symbolp lambda-expr)
7c1898a7 342 ("cl-function" cl-function)
b1198e17
SM
343 form))
344
ebacfcc6 345;;;###autoload
7c1898a7 346(defmacro cl-function (func)
64a4c526 347 "Introduce a function.
3187ba1c
JB
348Like normal `function', except that if argument is a lambda form,
349its argument list allows full Common Lisp conventions."
b1198e17 350 (declare (debug (&or symbolp cl-lambda-expr)))
fcd73769 351 (if (eq (car-safe func) 'lambda)
4dd1c416 352 (let* ((res (cl--transform-lambda (cdr func) 'cl-none))
03fef3e6
SM
353 (form `(function (lambda . ,(cdr res)))))
354 (if (car res) `(progn ,(car res) ,form) form))
355 `(function ,func)))
fcd73769 356
b4587710
JB
357(declare-function help-add-fundoc-usage "help-fns" (docstring arglist))
358
673e08bb
SM
359(defun cl--make-usage-var (x)
360 "X can be a var or a (destructuring) lambda-list."
361 (cond
362 ((symbolp x) (make-symbol (upcase (symbol-name x))))
363 ((consp x) (cl--make-usage-args x))
364 (t x)))
365
366(defun cl--make-usage-args (arglist)
367 ;; `orig-args' can contain &cl-defs (an internal
368 ;; CL thingy I don't understand), so remove it.
369 (let ((x (memq '&cl-defs arglist)))
370 (when x (setq arglist (delq (car x) (remq (cadr x) arglist)))))
371 (let ((state nil))
372 (mapcar (lambda (x)
373 (cond
374 ((symbolp x)
375 (if (eq ?\& (aref (symbol-name x) 0))
376 (setq state x)
377 (make-symbol (upcase (symbol-name x)))))
378 ((not (consp x)) x)
379 ((memq state '(nil &rest)) (cl--make-usage-args x))
380 (t ;(VAR INITFORM SVAR) or ((KEYWORD VAR) INITFORM SVAR).
7c1898a7 381 (cl-list*
673e08bb
SM
382 (if (and (consp (car x)) (eq state '&key))
383 (list (caar x) (cl--make-usage-var (nth 1 (car x))))
384 (cl--make-usage-var (car x)))
385 (nth 1 x) ;INITFORM.
386 (cl--make-usage-args (nthcdr 2 x)) ;SVAR.
387 ))))
388 arglist)))
389
4dd1c416 390(defun cl--do-arglist (args expr &optional num) ; uses bind-*
fcd73769 391 (if (nlistp args)
bb3faf5b 392 (if (or (memq args cl--lambda-list-keywords) (not (symbolp args)))
fcd73769 393 (error "Invalid argument name: %s" args)
513749ee 394 (push (list args expr) cl--bind-lets))
7c1898a7 395 (setq args (cl-copy-list args))
fcd73769
RS
396 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
397 (let ((p (memq '&body args))) (if p (setcar p '&rest)))
398 (if (memq '&environment args) (error "&environment used incorrectly"))
399 (let ((save-args args)
400 (restarg (memq '&rest args))
bb3faf5b 401 (safety (if (cl--compiling-file) cl-optimize-safety 3))
fcd73769
RS
402 (keys nil)
403 (laterarg nil) (exactarg nil) minarg)
404 (or num (setq num 0))
405 (if (listp (cadr restarg))
e542ea4b 406 (setq restarg (make-symbol "--cl-rest--"))
fcd73769 407 (setq restarg (cadr restarg)))
513749ee 408 (push (list restarg expr) cl--bind-lets)
fcd73769 409 (if (eq (car args) '&whole)
513749ee 410 (push (list (cl-pop2 args) restarg) cl--bind-lets))
fcd73769
RS
411 (let ((p args))
412 (setq minarg restarg)
bb3faf5b 413 (while (and p (not (memq (car p) cl--lambda-list-keywords)))
fcd73769
RS
414 (or (eq p args) (setq minarg (list 'cdr minarg)))
415 (setq p (cdr p)))
416 (if (memq (car p) '(nil &aux))
03fef3e6 417 (setq minarg `(= (length ,restarg)
7c1898a7 418 ,(length (cl-ldiff args p)))
fcd73769 419 exactarg (not (eq args p)))))
bb3faf5b 420 (while (and args (not (memq (car args) cl--lambda-list-keywords)))
fcd73769
RS
421 (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car)
422 restarg)))
4dd1c416 423 (cl--do-arglist
69d8fb1e 424 (pop args)
fcd73769 425 (if (or laterarg (= safety 0)) poparg
03fef3e6
SM
426 `(if ,minarg ,poparg
427 (signal 'wrong-number-of-arguments
513749ee
SM
428 (list ,(and (not (eq cl--bind-block 'cl-none))
429 `',cl--bind-block)
03fef3e6 430 (length ,restarg)))))))
fcd73769 431 (setq num (1+ num) laterarg t))
69d8fb1e 432 (while (and (eq (car args) '&optional) (pop args))
bb3faf5b 433 (while (and args (not (memq (car args) cl--lambda-list-keywords)))
69d8fb1e 434 (let ((arg (pop args)))
fcd73769 435 (or (consp arg) (setq arg (list arg)))
4dd1c416 436 (if (cddr arg) (cl--do-arglist (nth 2 arg) `(and ,restarg t)))
fcd73769 437 (let ((def (if (cdr arg) (nth 1 arg)
513749ee
SM
438 (or (car cl--bind-defs)
439 (nth 1 (assq (car arg) cl--bind-defs)))))
03fef3e6 440 (poparg `(pop ,restarg)))
513749ee 441 (and def cl--bind-enquote (setq def `',def))
4dd1c416 442 (cl--do-arglist (car arg)
03fef3e6 443 (if def `(if ,restarg ,poparg ,def) poparg))
fcd73769
RS
444 (setq num (1+ num))))))
445 (if (eq (car args) '&rest)
446 (let ((arg (cl-pop2 args)))
4dd1c416 447 (if (consp arg) (cl--do-arglist arg restarg)))
fcd73769 448 (or (eq (car args) '&key) (= safety 0) exactarg
03fef3e6
SM
449 (push `(if ,restarg
450 (signal 'wrong-number-of-arguments
451 (list
513749ee
SM
452 ,(and (not (eq cl--bind-block 'cl-none))
453 `',cl--bind-block)
03fef3e6 454 (+ ,num (length ,restarg)))))
513749ee 455 cl--bind-forms)))
69d8fb1e 456 (while (and (eq (car args) '&key) (pop args))
bb3faf5b 457 (while (and args (not (memq (car args) cl--lambda-list-keywords)))
69d8fb1e 458 (let ((arg (pop args)))
dd441b46 459 (or (consp arg) (setq arg (list arg)))
fcd73769
RS
460 (let* ((karg (if (consp (car arg)) (caar arg)
461 (intern (format ":%s" (car arg)))))
7c1898a7 462 (varg (if (consp (car arg)) (cl-cadar arg) (car arg)))
fcd73769 463 (def (if (cdr arg) (cadr arg)
513749ee 464 (or (car cl--bind-defs) (cadr (assq varg cl--bind-defs)))))
03fef3e6 465 (look `(memq ',karg ,restarg)))
513749ee 466 (and def cl--bind-enquote (setq def `',def))
fcd73769 467 (if (cddr arg)
e542ea4b 468 (let* ((temp (or (nth 2 arg) (make-symbol "--cl-var--")))
03fef3e6 469 (val `(car (cdr ,temp))))
4dd1c416
SM
470 (cl--do-arglist temp look)
471 (cl--do-arglist varg
03fef3e6
SM
472 `(if ,temp
473 (prog1 ,val (setq ,temp t))
474 ,def)))
4dd1c416 475 (cl--do-arglist
fcd73769 476 varg
03fef3e6 477 `(car (cdr ,(if (null def)
fcd73769 478 look
03fef3e6 479 `(or ,look
4dd1c416
SM
480 ,(if (eq (cl--const-expr-p def) t)
481 `'(nil ,(cl--const-expr-val def))
03fef3e6 482 `(list nil ,def))))))))
69d8fb1e 483 (push karg keys)))))
fcd73769 484 (setq keys (nreverse keys))
69d8fb1e 485 (or (and (eq (car args) '&allow-other-keys) (pop args))
fcd73769 486 (null keys) (= safety 0)
e542ea4b 487 (let* ((var (make-symbol "--cl-keys--"))
fcd73769 488 (allow '(:allow-other-keys))
03fef3e6
SM
489 (check `(while ,var
490 (cond
491 ((memq (car ,var) ',(append keys allow))
492 (setq ,var (cdr (cdr ,var))))
493 ((car (cdr (memq (quote ,@allow) ,restarg)))
494 (setq ,var nil))
495 (t
496 (error
497 ,(format "Keyword argument %%s not one of %s"
498 keys)
499 (car ,var)))))))
513749ee 500 (push `(let ((,var ,restarg)) ,check) cl--bind-forms)))
69d8fb1e 501 (while (and (eq (car args) '&aux) (pop args))
bb3faf5b 502 (while (and args (not (memq (car args) cl--lambda-list-keywords)))
fcd73769 503 (if (consp (car args))
513749ee 504 (if (and cl--bind-enquote (cl-cadar args))
4dd1c416 505 (cl--do-arglist (caar args)
03fef3e6 506 `',(cadr (pop args)))
4dd1c416
SM
507 (cl--do-arglist (caar args) (cadr (pop args))))
508 (cl--do-arglist (pop args) nil))))
fcd73769
RS
509 (if args (error "Malformed argument list %s" save-args)))))
510
4dd1c416 511(defun cl--arglist-args (args)
fcd73769
RS
512 (if (nlistp args) (list args)
513 (let ((res nil) (kind nil) arg)
514 (while (consp args)
69d8fb1e 515 (setq arg (pop args))
bb3faf5b 516 (if (memq arg cl--lambda-list-keywords) (setq kind arg)
69d8fb1e 517 (if (eq arg '&cl-defs) (pop args)
fcd73769
RS
518 (and (consp arg) kind (setq arg (car arg)))
519 (and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg)))
4dd1c416 520 (setq res (nconc res (cl--arglist-args arg))))))
fcd73769
RS
521 (nconc res (and args (list args))))))
522
ebacfcc6 523;;;###autoload
7c1898a7 524(defmacro cl-destructuring-bind (args expr &rest body)
70b8ef8f
SM
525 (declare (indent 2)
526 (debug (&define cl-macro-list def-form cl-declarations def-body)))
513749ee
SM
527 (let* ((cl--bind-lets nil) (cl--bind-forms nil) (cl--bind-inits nil)
528 (cl--bind-defs nil) (cl--bind-block 'cl-none) (cl--bind-enquote nil))
4dd1c416 529 (cl--do-arglist (or args '(&aux)) expr)
513749ee
SM
530 (append '(progn) cl--bind-inits
531 (list `(let* ,(nreverse cl--bind-lets)
532 ,@(nreverse cl--bind-forms) ,@body)))))
fcd73769
RS
533
534
7c1898a7 535;;; The `cl-eval-when' form.
fcd73769
RS
536
537(defvar cl-not-toplevel nil)
538
ebacfcc6 539;;;###autoload
7c1898a7 540(defmacro cl-eval-when (when &rest body)
69d8fb1e 541 "Control when BODY is evaluated.
fcd73769
RS
542If `compile' is in WHEN, BODY is evaluated when compiled at top-level.
543If `load' is in WHEN, BODY is evaluated when loaded after top-level compile.
69d8fb1e
SM
544If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level.
545
546\(fn (WHEN...) BODY...)"
70b8ef8f 547 (declare (indent 1) (debug ((&rest &or "compile" "load" "eval") body)))
bb3faf5b 548 (if (and (fboundp 'cl--compiling-file) (cl--compiling-file)
fcd73769 549 (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge
64a4c526 550 (let ((comp (or (memq 'compile when) (memq :compile-toplevel when)))
fcd73769 551 (cl-not-toplevel t))
64a4c526 552 (if (or (memq 'load when) (memq :load-toplevel when))
4dd1c416 553 (if comp (cons 'progn (mapcar 'cl--compile-time-too body))
03fef3e6 554 `(if nil nil ,@body))
fcd73769 555 (progn (if comp (eval (cons 'progn body))) nil)))
64a4c526 556 (and (or (memq 'eval when) (memq :execute when))
fcd73769
RS
557 (cons 'progn body))))
558
4dd1c416 559(defun cl--compile-time-too (form)
fcd73769
RS
560 (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler))
561 (setq form (macroexpand
7c1898a7 562 form (cons '(cl-eval-when) byte-compile-macro-environment))))
fcd73769 563 (cond ((eq (car-safe form) 'progn)
4dd1c416 564 (cons 'progn (mapcar 'cl--compile-time-too (cdr form))))
7c1898a7 565 ((eq (car-safe form) 'cl-eval-when)
fcd73769 566 (let ((when (nth 1 form)))
64a4c526 567 (if (or (memq 'eval when) (memq :execute when))
7c1898a7 568 `(cl-eval-when (compile ,@when) ,@(cddr form))
fcd73769
RS
569 form)))
570 (t (eval form) form)))
571
ebacfcc6 572;;;###autoload
513749ee 573(defmacro cl-load-time-value (form &optional _read-only)
fcd73769
RS
574 "Like `progn', but evaluates the body at load time.
575The result of the body appears to the compiler as a quoted constant."
b1198e17 576 (declare (debug (form &optional sexp)))
bb3faf5b 577 (if (cl--compiling-file)
7c1898a7 578 (let* ((temp (cl-gentemp "--cl-load-time--"))
03fef3e6 579 (set `(set ',temp ,form)))
fcd73769
RS
580 (if (and (fboundp 'byte-compile-file-form-defmumble)
581 (boundp 'this-kind) (boundp 'that-one))
582 (fset 'byte-compile-file-form
03fef3e6
SM
583 `(lambda (form)
584 (fset 'byte-compile-file-form
585 ',(symbol-function 'byte-compile-file-form))
586 (byte-compile-file-form ',set)
587 (byte-compile-file-form form)))
7200d79c 588 (print set (symbol-value 'byte-compile--outbuffer)))
03fef3e6
SM
589 `(symbol-value ',temp))
590 `',(eval form)))
fcd73769
RS
591
592
593;;; Conditional control structures.
594
ebacfcc6 595;;;###autoload
7c1898a7 596(defmacro cl-case (expr &rest clauses)
3187ba1c 597 "Eval EXPR and choose among clauses on that value.
fcd73769
RS
598Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared
599against each key in each KEYLIST; the corresponding BODY is evaluated.
7c1898a7 600If no clause succeeds, cl-case returns nil. A single atom may be used in
a8ea72a0 601place of a KEYLIST of one atom. A KEYLIST of t or `otherwise' is
fcd73769 602allowed only in the final clause, and matches if no other keys match.
3187ba1c
JB
603Key values are compared by `eql'.
604\n(fn EXPR (KEYLIST BODY...)...)"
70b8ef8f 605 (declare (indent 1) (debug (form &rest (sexp body))))
4dd1c416 606 (let* ((temp (if (cl--simple-expr-p expr 3) expr (make-symbol "--cl-var--")))
fcd73769
RS
607 (head-list nil)
608 (body (cons
609 'cond
610 (mapcar
611 (function
612 (lambda (c)
613 (cons (cond ((memq (car c) '(t otherwise)) t)
7c1898a7
SM
614 ((eq (car c) 'cl--ecase-error-flag)
615 `(error "cl-ecase failed: %s, %s"
03fef3e6 616 ,temp ',(reverse head-list)))
fcd73769
RS
617 ((listp (car c))
618 (setq head-list (append (car c) head-list))
7c1898a7 619 `(cl-member ,temp ',(car c)))
fcd73769
RS
620 (t
621 (if (memq (car c) head-list)
622 (error "Duplicate key in case: %s"
623 (car c)))
69d8fb1e 624 (push (car c) head-list)
03fef3e6 625 `(eql ,temp ',(car c))))
fcd73769
RS
626 (or (cdr c) '(nil)))))
627 clauses))))
628 (if (eq temp expr) body
03fef3e6 629 `(let ((,temp ,expr)) ,body))))
fcd73769 630
ebacfcc6 631;;;###autoload
7c1898a7
SM
632(defmacro cl-ecase (expr &rest clauses)
633 "Like `cl-case', but error if no cl-case fits.
3187ba1c
JB
634`otherwise'-clauses are not allowed.
635\n(fn EXPR (KEYLIST BODY...)...)"
7c1898a7
SM
636 (declare (indent 1) (debug cl-case))
637 `(cl-case ,expr ,@clauses (cl--ecase-error-flag)))
fcd73769 638
ebacfcc6 639;;;###autoload
7c1898a7 640(defmacro cl-typecase (expr &rest clauses)
3187ba1c 641 "Evals EXPR, chooses among clauses on that value.
fcd73769
RS
642Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it
643satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds,
7c1898a7 644cl-typecase returns nil. A TYPE of t or `otherwise' is allowed only in the
3187ba1c
JB
645final clause, and matches if no other keys match.
646\n(fn EXPR (TYPE BODY...)...)"
70b8ef8f
SM
647 (declare (indent 1)
648 (debug (form &rest ([&or cl-type-spec "otherwise"] body))))
4dd1c416 649 (let* ((temp (if (cl--simple-expr-p expr 3) expr (make-symbol "--cl-var--")))
fcd73769
RS
650 (type-list nil)
651 (body (cons
652 'cond
653 (mapcar
654 (function
655 (lambda (c)
656 (cons (cond ((eq (car c) 'otherwise) t)
7c1898a7
SM
657 ((eq (car c) 'cl--ecase-error-flag)
658 `(error "cl-etypecase failed: %s, %s"
03fef3e6 659 ,temp ',(reverse type-list)))
fcd73769 660 (t
69d8fb1e 661 (push (car c) type-list)
4dd1c416 662 (cl--make-type-test temp (car c))))
fcd73769
RS
663 (or (cdr c) '(nil)))))
664 clauses))))
665 (if (eq temp expr) body
03fef3e6 666 `(let ((,temp ,expr)) ,body))))
fcd73769 667
ebacfcc6 668;;;###autoload
7c1898a7
SM
669(defmacro cl-etypecase (expr &rest clauses)
670 "Like `cl-typecase', but error if no case fits.
3187ba1c
JB
671`otherwise'-clauses are not allowed.
672\n(fn EXPR (TYPE BODY...)...)"
7c1898a7
SM
673 (declare (indent 1) (debug cl-typecase))
674 `(cl-typecase ,expr ,@clauses (cl--ecase-error-flag)))
fcd73769
RS
675
676
677;;; Blocks and exits.
678
ebacfcc6 679;;;###autoload
7c1898a7 680(defmacro cl-block (name &rest body)
64a4c526 681 "Define a lexically-scoped block named NAME.
7c1898a7 682NAME may be any symbol. Code inside the BODY forms can call `cl-return-from'
fcd73769
RS
683to jump prematurely out of the block. This differs from `catch' and `throw'
684in two respects: First, the NAME is an unevaluated symbol rather than a
685quoted symbol or other form; and second, NAME is lexically rather than
686dynamically scoped: Only references to it within BODY will work. These
687references may appear inside macro expansions, but not inside functions
688called from BODY."
70b8ef8f 689 (declare (indent 1) (debug (symbolp body)))
4dd1c416 690 (if (cl--safe-expr-p `(progn ,@body)) `(progn ,@body)
bb3faf5b 691 `(cl--block-wrapper
03fef3e6
SM
692 (catch ',(intern (format "--cl-block-%s--" name))
693 ,@body))))
fcd73769 694
ebacfcc6 695;;;###autoload
7c1898a7 696(defmacro cl-return (&optional result)
64a4c526 697 "Return from the block named nil.
7c1898a7 698This is equivalent to `(cl-return-from nil RESULT)'."
b1198e17 699 (declare (debug (&optional form)))
7c1898a7 700 `(cl-return-from nil ,result))
fcd73769 701
ebacfcc6 702;;;###autoload
7c1898a7 703(defmacro cl-return-from (name &optional result)
64a4c526 704 "Return from the block named NAME.
7c1898a7 705This jumps out to the innermost enclosing `(cl-block NAME ...)' form,
fcd73769
RS
706returning RESULT from that form (or nil if RESULT is omitted).
707This is compatible with Common Lisp, but note that `defun' and
708`defmacro' do not create implicit blocks as they do in Common Lisp."
70b8ef8f 709 (declare (indent 1) (debug (symbolp &optional form)))
fcd73769 710 (let ((name2 (intern (format "--cl-block-%s--" name))))
bb3faf5b 711 `(cl--block-throw ',name2 ,result)))
fcd73769
RS
712
713
7c1898a7 714;;; The "cl-loop" macro.
fcd73769 715
4dd1c416
SM
716(defvar cl--loop-args) (defvar cl--loop-accum-var) (defvar cl--loop-accum-vars)
717(defvar cl--loop-bindings) (defvar cl--loop-body) (defvar cl--loop-destr-temps)
718(defvar cl--loop-finally) (defvar cl--loop-finish-flag)
719(defvar cl--loop-first-flag)
720(defvar cl--loop-initially) (defvar cl--loop-map-form) (defvar cl--loop-name)
721(defvar cl--loop-result) (defvar cl--loop-result-explicit)
722(defvar cl--loop-result-var) (defvar cl--loop-steps) (defvar cl--loop-symbol-macs)
fcd73769 723
ebacfcc6 724;;;###autoload
513749ee 725(defmacro cl-loop (&rest loop-args)
7c1898a7 726 "The Common Lisp `cl-loop' macro.
fcd73769
RS
727Valid clauses are:
728 for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM,
729 for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR,
730 for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND,
731 always COND, never COND, thereis COND, collect EXPR into VAR,
732 append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR,
733 count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR,
734 if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
735 unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
736 do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR,
69d8fb1e
SM
737 finally return EXPR, named NAME.
738
739\(fn CLAUSE...)"
b1198e17 740 (declare (debug (&rest &or symbolp form)))
513749ee
SM
741 (if (not (memq t (mapcar 'symbolp (delq nil (delq t (cl-copy-list loop-args))))))
742 `(cl-block nil (while t ,@loop-args))
743 (let ((cl--loop-args loop-args) (cl--loop-name nil) (cl--loop-bindings nil)
4dd1c416
SM
744 (cl--loop-body nil) (cl--loop-steps nil)
745 (cl--loop-result nil) (cl--loop-result-explicit nil)
746 (cl--loop-result-var nil) (cl--loop-finish-flag nil)
747 (cl--loop-accum-var nil) (cl--loop-accum-vars nil)
748 (cl--loop-initially nil) (cl--loop-finally nil)
749 (cl--loop-map-form nil) (cl--loop-first-flag nil)
750 (cl--loop-destr-temps nil) (cl--loop-symbol-macs nil))
751 (setq cl--loop-args (append cl--loop-args '(cl-end-loop)))
752 (while (not (eq (car cl--loop-args) 'cl-end-loop)) (cl-parse-loop-clause))
753 (if cl--loop-finish-flag
754 (push `((,cl--loop-finish-flag t)) cl--loop-bindings))
755 (if cl--loop-first-flag
756 (progn (push `((,cl--loop-first-flag t)) cl--loop-bindings)
757 (push `(setq ,cl--loop-first-flag nil) cl--loop-steps)))
758 (let* ((epilogue (nconc (nreverse cl--loop-finally)
759 (list (or cl--loop-result-explicit cl--loop-result))))
760 (ands (cl--loop-build-ands (nreverse cl--loop-body)))
761 (while-body (nconc (cadr ands) (nreverse cl--loop-steps)))
fcd73769 762 (body (append
4dd1c416
SM
763 (nreverse cl--loop-initially)
764 (list (if cl--loop-map-form
7c1898a7
SM
765 `(cl-block --cl-finish--
766 ,(cl-subst
03fef3e6
SM
767 (if (eq (car ands) t) while-body
768 (cons `(or ,(car ands)
7c1898a7 769 (cl-return-from --cl-finish--
03fef3e6
SM
770 nil))
771 while-body))
4dd1c416 772 '--cl-map cl--loop-map-form))
03fef3e6 773 `(while ,(car ands) ,@while-body)))
4dd1c416
SM
774 (if cl--loop-finish-flag
775 (if (equal epilogue '(nil)) (list cl--loop-result-var)
776 `((if ,cl--loop-finish-flag
777 (progn ,@epilogue) ,cl--loop-result-var)))
fcd73769 778 epilogue))))
4dd1c416
SM
779 (if cl--loop-result-var (push (list cl--loop-result-var) cl--loop-bindings))
780 (while cl--loop-bindings
781 (if (cdar cl--loop-bindings)
782 (setq body (list (cl--loop-let (pop cl--loop-bindings) body t)))
fcd73769 783 (let ((lets nil))
4dd1c416
SM
784 (while (and cl--loop-bindings
785 (not (cdar cl--loop-bindings)))
786 (push (car (pop cl--loop-bindings)) lets))
787 (setq body (list (cl--loop-let lets body nil))))))
788 (if cl--loop-symbol-macs
789 (setq body (list `(cl-symbol-macrolet ,cl--loop-symbol-macs ,@body))))
790 `(cl-block ,cl--loop-name ,@body)))))
fcd73769 791
7c1898a7 792;; Below is a complete spec for cl-loop, in several parts that correspond
b1198e17
SM
793;; to the syntax given in CLtL2. The specs do more than specify where
794;; the forms are; it also specifies, as much as Edebug allows, all the
7c1898a7 795;; syntactically valid cl-loop clauses. The disadvantage of this
b1198e17
SM
796;; completeness is rigidity, but the "for ... being" clause allows
797;; arbitrary extensions of the form: [symbolp &rest &or symbolp form].
798
7c1898a7 799;; (def-edebug-spec cl-loop
b1198e17
SM
800;; ([&optional ["named" symbolp]]
801;; [&rest
802;; &or
803;; ["repeat" form]
804;; loop-for-as
805;; loop-with
806;; loop-initial-final]
807;; [&rest loop-clause]
808;; ))
809
810;; (def-edebug-spec loop-with
811;; ("with" loop-var
812;; loop-type-spec
813;; [&optional ["=" form]]
814;; &rest ["and" loop-var
815;; loop-type-spec
816;; [&optional ["=" form]]]))
817
818;; (def-edebug-spec loop-for-as
819;; ([&or "for" "as"] loop-for-as-subclause
820;; &rest ["and" loop-for-as-subclause]))
821
822;; (def-edebug-spec loop-for-as-subclause
823;; (loop-var
824;; loop-type-spec
825;; &or
826;; [[&or "in" "on" "in-ref" "across-ref"]
827;; form &optional ["by" function-form]]
828
829;; ["=" form &optional ["then" form]]
830;; ["across" form]
831;; ["being"
832;; [&or "the" "each"]
833;; &or
834;; [[&or "element" "elements"]
835;; [&or "of" "in" "of-ref"] form
836;; &optional "using" ["index" symbolp]];; is this right?
837;; [[&or "hash-key" "hash-keys"
838;; "hash-value" "hash-values"]
839;; [&or "of" "in"]
840;; hash-table-p &optional ["using" ([&or "hash-value" "hash-values"
841;; "hash-key" "hash-keys"] sexp)]]
842
843;; [[&or "symbol" "present-symbol" "external-symbol"
844;; "symbols" "present-symbols" "external-symbols"]
845;; [&or "in" "of"] package-p]
846
847;; ;; Extensions for Emacs Lisp, including Lucid Emacs.
848;; [[&or "frame" "frames"
849;; "screen" "screens"
850;; "buffer" "buffers"]]
851
852;; [[&or "window" "windows"]
853;; [&or "of" "in"] form]
854
855;; [[&or "overlay" "overlays"
856;; "extent" "extents"]
857;; [&or "of" "in"] form
858;; &optional [[&or "from" "to"] form]]
859
860;; [[&or "interval" "intervals"]
861;; [&or "in" "of"] form
862;; &optional [[&or "from" "to"] form]
863;; ["property" form]]
864
865;; [[&or "key-code" "key-codes"
866;; "key-seq" "key-seqs"
867;; "key-binding" "key-bindings"]
868;; [&or "in" "of"] form
869;; &optional ["using" ([&or "key-code" "key-codes"
870;; "key-seq" "key-seqs"
871;; "key-binding" "key-bindings"]
872;; sexp)]]
873;; ;; For arbitrary extensions, recognize anything else.
874;; [symbolp &rest &or symbolp form]
875;; ]
876
877;; ;; arithmetic - must be last since all parts are optional.
878;; [[&optional [[&or "from" "downfrom" "upfrom"] form]]
879;; [&optional [[&or "to" "downto" "upto" "below" "above"] form]]
880;; [&optional ["by" form]]
881;; ]))
882
883;; (def-edebug-spec loop-initial-final
884;; (&or ["initially"
885;; ;; [&optional &or "do" "doing"] ;; CLtL2 doesn't allow this.
886;; &rest loop-non-atomic-expr]
887;; ["finally" &or
888;; [[&optional &or "do" "doing"] &rest loop-non-atomic-expr]
889;; ["return" form]]))
890
891;; (def-edebug-spec loop-and-clause
892;; (loop-clause &rest ["and" loop-clause]))
893
894;; (def-edebug-spec loop-clause
895;; (&or
896;; [[&or "while" "until" "always" "never" "thereis"] form]
897
898;; [[&or "collect" "collecting"
899;; "append" "appending"
900;; "nconc" "nconcing"
901;; "concat" "vconcat"] form
902;; [&optional ["into" loop-var]]]
903
904;; [[&or "count" "counting"
905;; "sum" "summing"
906;; "maximize" "maximizing"
907;; "minimize" "minimizing"] form
908;; [&optional ["into" loop-var]]
909;; loop-type-spec]
910
911;; [[&or "if" "when" "unless"]
912;; form loop-and-clause
913;; [&optional ["else" loop-and-clause]]
914;; [&optional "end"]]
915
916;; [[&or "do" "doing"] &rest loop-non-atomic-expr]
917
918;; ["return" form]
919;; loop-initial-final
920;; ))
921
922;; (def-edebug-spec loop-non-atomic-expr
923;; ([&not atom] form))
924
925;; (def-edebug-spec loop-var
926;; ;; The symbolp must be last alternative to recognize e.g. (a b . c)
927;; ;; loop-var =>
928;; ;; (loop-var . [&or nil loop-var])
929;; ;; (symbolp . [&or nil loop-var])
930;; ;; (symbolp . loop-var)
931;; ;; (symbolp . (symbolp . [&or nil loop-var]))
932;; ;; (symbolp . (symbolp . loop-var))
933;; ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp)
934;; (&or (loop-var . [&or nil loop-var]) [gate symbolp]))
935
936;; (def-edebug-spec loop-type-spec
937;; (&optional ["of-type" loop-d-type-spec]))
938
939;; (def-edebug-spec loop-d-type-spec
940;; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
941
942
943
215461a8 944(defun cl-parse-loop-clause () ; uses loop-*
4dd1c416 945 (let ((word (pop cl--loop-args))
fcd73769
RS
946 (hash-types '(hash-key hash-keys hash-value hash-values))
947 (key-types '(key-code key-codes key-seq key-seqs
948 key-binding key-bindings)))
949 (cond
950
4dd1c416 951 ((null cl--loop-args)
7c1898a7 952 (error "Malformed `cl-loop' macro"))
fcd73769
RS
953
954 ((eq word 'named)
4dd1c416 955 (setq cl--loop-name (pop cl--loop-args)))
fcd73769
RS
956
957 ((eq word 'initially)
4dd1c416
SM
958 (if (memq (car cl--loop-args) '(do doing)) (pop cl--loop-args))
959 (or (consp (car cl--loop-args)) (error "Syntax error on `initially' clause"))
960 (while (consp (car cl--loop-args))
961 (push (pop cl--loop-args) cl--loop-initially)))
fcd73769
RS
962
963 ((eq word 'finally)
4dd1c416
SM
964 (if (eq (car cl--loop-args) 'return)
965 (setq cl--loop-result-explicit (or (cl-pop2 cl--loop-args) '(quote nil)))
966 (if (memq (car cl--loop-args) '(do doing)) (pop cl--loop-args))
967 (or (consp (car cl--loop-args)) (error "Syntax error on `finally' clause"))
968 (if (and (eq (caar cl--loop-args) 'return) (null cl--loop-name))
969 (setq cl--loop-result-explicit (or (nth 1 (pop cl--loop-args)) '(quote nil)))
970 (while (consp (car cl--loop-args))
971 (push (pop cl--loop-args) cl--loop-finally)))))
fcd73769
RS
972
973 ((memq word '(for as))
974 (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil)
975 (ands nil))
976 (while
7c1898a7 977 ;; Use `cl-gensym' rather than `make-symbol'. It's important that
443b961a 978 ;; (not (eq (symbol-name var1) (symbol-name var2))) because
4dd1c416
SM
979 ;; these vars get added to the macro-environment.
980 (let ((var (or (pop cl--loop-args) (cl-gensym "--cl-var--"))))
981 (setq word (pop cl--loop-args))
982 (if (eq word 'being) (setq word (pop cl--loop-args)))
983 (if (memq word '(the each)) (setq word (pop cl--loop-args)))
fcd73769 984 (if (memq word '(buffer buffers))
4dd1c416 985 (setq word 'in cl--loop-args (cons '(buffer-list) cl--loop-args)))
fcd73769
RS
986 (cond
987
988 ((memq word '(from downfrom upfrom to downto upto
989 above below by))
4dd1c416
SM
990 (push word cl--loop-args)
991 (if (memq (car cl--loop-args) '(downto above))
7c1898a7 992 (error "Must specify `from' value for downward cl-loop"))
4dd1c416
SM
993 (let* ((down (or (eq (car cl--loop-args) 'downfrom)
994 (memq (cl-caddr cl--loop-args) '(downto above))))
995 (excl (or (memq (car cl--loop-args) '(above below))
996 (memq (cl-caddr cl--loop-args) '(above below))))
997 (start (and (memq (car cl--loop-args) '(from upfrom downfrom))
998 (cl-pop2 cl--loop-args)))
999 (end (and (memq (car cl--loop-args)
fcd73769 1000 '(to upto downto above below))
4dd1c416
SM
1001 (cl-pop2 cl--loop-args)))
1002 (step (and (eq (car cl--loop-args) 'by) (cl-pop2 cl--loop-args)))
1003 (end-var (and (not (macroexp-const-p end))
e542ea4b 1004 (make-symbol "--cl-var--")))
4dd1c416 1005 (step-var (and (not (macroexp-const-p step))
e542ea4b 1006 (make-symbol "--cl-var--"))))
fcd73769
RS
1007 (and step (numberp step) (<= step 0)
1008 (error "Loop `by' value is not positive: %s" step))
69d8fb1e
SM
1009 (push (list var (or start 0)) loop-for-bindings)
1010 (if end-var (push (list end-var end) loop-for-bindings))
1011 (if step-var (push (list step-var step)
e542ea4b 1012 loop-for-bindings))
fcd73769 1013 (if end
69d8fb1e 1014 (push (list
e542ea4b 1015 (if down (if excl '> '>=) (if excl '< '<=))
4dd1c416 1016 var (or end-var end)) cl--loop-body))
69d8fb1e 1017 (push (list var (list (if down '- '+) var
e542ea4b
SM
1018 (or step-var step 1)))
1019 loop-for-steps)))
fcd73769
RS
1020
1021 ((memq word '(in in-ref on))
1022 (let* ((on (eq word 'on))
e542ea4b
SM
1023 (temp (if (and on (symbolp var))
1024 var (make-symbol "--cl-var--"))))
4dd1c416
SM
1025 (push (list temp (pop cl--loop-args)) loop-for-bindings)
1026 (push `(consp ,temp) cl--loop-body)
fcd73769 1027 (if (eq word 'in-ref)
4dd1c416 1028 (push (list var `(car ,temp)) cl--loop-symbol-macs)
fcd73769
RS
1029 (or (eq temp var)
1030 (progn
69d8fb1e 1031 (push (list var nil) loop-for-bindings)
03fef3e6 1032 (push (list var (if on temp `(car ,temp)))
e542ea4b 1033 loop-for-sets))))
69d8fb1e 1034 (push (list temp
4dd1c416
SM
1035 (if (eq (car cl--loop-args) 'by)
1036 (let ((step (cl-pop2 cl--loop-args)))
e542ea4b
SM
1037 (if (and (memq (car-safe step)
1038 '(quote function
7c1898a7 1039 cl-function))
e542ea4b
SM
1040 (symbolp (nth 1 step)))
1041 (list (nth 1 step) temp)
03fef3e6
SM
1042 `(funcall ,step ,temp)))
1043 `(cdr ,temp)))
e542ea4b 1044 loop-for-steps)))
fcd73769
RS
1045
1046 ((eq word '=)
4dd1c416
SM
1047 (let* ((start (pop cl--loop-args))
1048 (then (if (eq (car cl--loop-args) 'then) (cl-pop2 cl--loop-args) start)))
69d8fb1e 1049 (push (list var nil) loop-for-bindings)
4dd1c416 1050 (if (or ands (eq (car cl--loop-args) 'and))
fcd73769 1051 (progn
e542ea4b 1052 (push `(,var
4dd1c416
SM
1053 (if ,(or cl--loop-first-flag
1054 (setq cl--loop-first-flag
e542ea4b
SM
1055 (make-symbol "--cl-var--")))
1056 ,start ,var))
1057 loop-for-sets)
69d8fb1e
SM
1058 (push (list var then) loop-for-steps))
1059 (push (list var
e542ea4b 1060 (if (eq start then) start
4dd1c416
SM
1061 `(if ,(or cl--loop-first-flag
1062 (setq cl--loop-first-flag
e542ea4b
SM
1063 (make-symbol "--cl-var--")))
1064 ,start ,then)))
1065 loop-for-sets))))
fcd73769
RS
1066
1067 ((memq word '(across across-ref))
e542ea4b
SM
1068 (let ((temp-vec (make-symbol "--cl-vec--"))
1069 (temp-idx (make-symbol "--cl-idx--")))
4dd1c416 1070 (push (list temp-vec (pop cl--loop-args)) loop-for-bindings)
69d8fb1e 1071 (push (list temp-idx -1) loop-for-bindings)
03fef3e6 1072 (push `(< (setq ,temp-idx (1+ ,temp-idx))
4dd1c416 1073 (length ,temp-vec)) cl--loop-body)
fcd73769 1074 (if (eq word 'across-ref)
03fef3e6 1075 (push (list var `(aref ,temp-vec ,temp-idx))
4dd1c416 1076 cl--loop-symbol-macs)
69d8fb1e 1077 (push (list var nil) loop-for-bindings)
03fef3e6 1078 (push (list var `(aref ,temp-vec ,temp-idx))
e542ea4b 1079 loop-for-sets))))
fcd73769
RS
1080
1081 ((memq word '(element elements))
4dd1c416
SM
1082 (let ((ref (or (memq (car cl--loop-args) '(in-ref of-ref))
1083 (and (not (memq (car cl--loop-args) '(in of)))
fcd73769 1084 (error "Expected `of'"))))
4dd1c416 1085 (seq (cl-pop2 cl--loop-args))
e542ea4b 1086 (temp-seq (make-symbol "--cl-seq--"))
4dd1c416
SM
1087 (temp-idx (if (eq (car cl--loop-args) 'using)
1088 (if (and (= (length (cadr cl--loop-args)) 2)
1089 (eq (cl-caadr cl--loop-args) 'index))
1090 (cadr (cl-pop2 cl--loop-args))
fcd73769 1091 (error "Bad `using' clause"))
e542ea4b 1092 (make-symbol "--cl-idx--"))))
69d8fb1e
SM
1093 (push (list temp-seq seq) loop-for-bindings)
1094 (push (list temp-idx 0) loop-for-bindings)
fcd73769 1095 (if ref
e542ea4b 1096 (let ((temp-len (make-symbol "--cl-len--")))
03fef3e6 1097 (push (list temp-len `(length ,temp-seq))
e542ea4b 1098 loop-for-bindings)
2eb87922 1099 (push (list var `(elt ,temp-seq ,temp-idx))
4dd1c416
SM
1100 cl--loop-symbol-macs)
1101 (push `(< ,temp-idx ,temp-len) cl--loop-body))
69d8fb1e 1102 (push (list var nil) loop-for-bindings)
03fef3e6
SM
1103 (push `(and ,temp-seq
1104 (or (consp ,temp-seq)
1105 (< ,temp-idx (length ,temp-seq))))
4dd1c416 1106 cl--loop-body)
03fef3e6
SM
1107 (push (list var `(if (consp ,temp-seq)
1108 (pop ,temp-seq)
1109 (aref ,temp-seq ,temp-idx)))
e542ea4b 1110 loop-for-sets))
03fef3e6 1111 (push (list temp-idx `(1+ ,temp-idx))
e542ea4b 1112 loop-for-steps)))
fcd73769
RS
1113
1114 ((memq word hash-types)
4dd1c416
SM
1115 (or (memq (car cl--loop-args) '(in of)) (error "Expected `of'"))
1116 (let* ((table (cl-pop2 cl--loop-args))
1117 (other (if (eq (car cl--loop-args) 'using)
1118 (if (and (= (length (cadr cl--loop-args)) 2)
1119 (memq (cl-caadr cl--loop-args) hash-types)
1120 (not (eq (cl-caadr cl--loop-args) word)))
1121 (cadr (cl-pop2 cl--loop-args))
fcd73769 1122 (error "Bad `using' clause"))
e542ea4b 1123 (make-symbol "--cl-var--"))))
fcd73769
RS
1124 (if (memq word '(hash-value hash-values))
1125 (setq var (prog1 other (setq other var))))
4dd1c416 1126 (setq cl--loop-map-form
e542ea4b 1127 `(maphash (lambda (,var ,other) . --cl-map) ,table))))
fcd73769
RS
1128
1129 ((memq word '(symbol present-symbol external-symbol
1130 symbols present-symbols external-symbols))
4dd1c416
SM
1131 (let ((ob (and (memq (car cl--loop-args) '(in of)) (cl-pop2 cl--loop-args))))
1132 (setq cl--loop-map-form
e542ea4b 1133 `(mapatoms (lambda (,var) . --cl-map) ,ob))))
fcd73769
RS
1134
1135 ((memq word '(overlay overlays extent extents))
1136 (let ((buf nil) (from nil) (to nil))
4dd1c416
SM
1137 (while (memq (car cl--loop-args) '(in of from to))
1138 (cond ((eq (car cl--loop-args) 'from) (setq from (cl-pop2 cl--loop-args)))
1139 ((eq (car cl--loop-args) 'to) (setq to (cl-pop2 cl--loop-args)))
1140 (t (setq buf (cl-pop2 cl--loop-args)))))
1141 (setq cl--loop-map-form
bb3faf5b 1142 `(cl--map-overlays
e542ea4b
SM
1143 (lambda (,var ,(make-symbol "--cl-var--"))
1144 (progn . --cl-map) nil)
1145 ,buf ,from ,to))))
fcd73769
RS
1146
1147 ((memq word '(interval intervals))
1148 (let ((buf nil) (prop nil) (from nil) (to nil)
e542ea4b
SM
1149 (var1 (make-symbol "--cl-var1--"))
1150 (var2 (make-symbol "--cl-var2--")))
4dd1c416
SM
1151 (while (memq (car cl--loop-args) '(in of property from to))
1152 (cond ((eq (car cl--loop-args) 'from) (setq from (cl-pop2 cl--loop-args)))
1153 ((eq (car cl--loop-args) 'to) (setq to (cl-pop2 cl--loop-args)))
1154 ((eq (car cl--loop-args) 'property)
1155 (setq prop (cl-pop2 cl--loop-args)))
1156 (t (setq buf (cl-pop2 cl--loop-args)))))
fcd73769
RS
1157 (if (and (consp var) (symbolp (car var)) (symbolp (cdr var)))
1158 (setq var1 (car var) var2 (cdr var))
03fef3e6 1159 (push (list var `(cons ,var1 ,var2)) loop-for-sets))
4dd1c416 1160 (setq cl--loop-map-form
bb3faf5b 1161 `(cl--map-intervals
e542ea4b
SM
1162 (lambda (,var1 ,var2) . --cl-map)
1163 ,buf ,prop ,from ,to))))
fcd73769
RS
1164
1165 ((memq word key-types)
4dd1c416
SM
1166 (or (memq (car cl--loop-args) '(in of)) (error "Expected `of'"))
1167 (let ((cl-map (cl-pop2 cl--loop-args))
1168 (other (if (eq (car cl--loop-args) 'using)
1169 (if (and (= (length (cadr cl--loop-args)) 2)
1170 (memq (cl-caadr cl--loop-args) key-types)
1171 (not (eq (cl-caadr cl--loop-args) word)))
1172 (cadr (cl-pop2 cl--loop-args))
fcd73769 1173 (error "Bad `using' clause"))
e542ea4b 1174 (make-symbol "--cl-var--"))))
fcd73769
RS
1175 (if (memq word '(key-binding key-bindings))
1176 (setq var (prog1 other (setq other var))))
4dd1c416 1177 (setq cl--loop-map-form
e542ea4b 1178 `(,(if (memq word '(key-seq key-seqs))
bb3faf5b 1179 'cl--map-keymap-recursively 'map-keymap)
7c1898a7 1180 (lambda (,var ,other) . --cl-map) ,cl-map))))
fcd73769
RS
1181
1182 ((memq word '(frame frames screen screens))
e542ea4b 1183 (let ((temp (make-symbol "--cl-var--")))
69d8fb1e 1184 (push (list var '(selected-frame))
e542ea4b 1185 loop-for-bindings)
69d8fb1e 1186 (push (list temp nil) loop-for-bindings)
03fef3e6
SM
1187 (push `(prog1 (not (eq ,var ,temp))
1188 (or ,temp (setq ,temp ,var)))
4dd1c416 1189 cl--loop-body)
03fef3e6 1190 (push (list var `(next-frame ,var))
e542ea4b 1191 loop-for-steps)))
fcd73769
RS
1192
1193 ((memq word '(window windows))
4dd1c416 1194 (let ((scr (and (memq (car cl--loop-args) '(in of)) (cl-pop2 cl--loop-args)))
05907bb3
GM
1195 (temp (make-symbol "--cl-var--"))
1196 (minip (make-symbol "--cl-minip--")))
69d8fb1e 1197 (push (list var (if scr
03fef3e6 1198 `(frame-selected-window ,scr)
e542ea4b
SM
1199 '(selected-window)))
1200 loop-for-bindings)
05907bb3
GM
1201 ;; If we started in the minibuffer, we need to
1202 ;; ensure that next-window will bring us back there
1203 ;; at some point. (Bug#7492).
7c1898a7 1204 ;; (Consider using walk-windows instead of cl-loop if
05907bb3
GM
1205 ;; you care about such things.)
1206 (push (list minip `(minibufferp (window-buffer ,var)))
1207 loop-for-bindings)
69d8fb1e 1208 (push (list temp nil) loop-for-bindings)
03fef3e6
SM
1209 (push `(prog1 (not (eq ,var ,temp))
1210 (or ,temp (setq ,temp ,var)))
4dd1c416 1211 cl--loop-body)
03fef3e6 1212 (push (list var `(next-window ,var ,minip))
05907bb3 1213 loop-for-steps)))
fcd73769
RS
1214
1215 (t
1216 (let ((handler (and (symbolp word)
4dd1c416 1217 (get word 'cl--loop-for-handler))))
fcd73769
RS
1218 (if handler
1219 (funcall handler var)
1220 (error "Expected a `for' preposition, found %s" word)))))
4dd1c416 1221 (eq (car cl--loop-args) 'and))
fcd73769 1222 (setq ands t)
4dd1c416 1223 (pop cl--loop-args))
fcd73769 1224 (if (and ands loop-for-bindings)
4dd1c416
SM
1225 (push (nreverse loop-for-bindings) cl--loop-bindings)
1226 (setq cl--loop-bindings (nconc (mapcar 'list loop-for-bindings)
1227 cl--loop-bindings)))
fcd73769 1228 (if loop-for-sets
03fef3e6 1229 (push `(progn
4dd1c416
SM
1230 ,(cl--loop-let (nreverse loop-for-sets) 'setq ands)
1231 t) cl--loop-body))
fcd73769 1232 (if loop-for-steps
7c1898a7 1233 (push (cons (if ands 'cl-psetq 'setq)
e542ea4b 1234 (apply 'append (nreverse loop-for-steps)))
4dd1c416 1235 cl--loop-steps))))
fcd73769
RS
1236
1237 ((eq word 'repeat)
e542ea4b 1238 (let ((temp (make-symbol "--cl-var--")))
4dd1c416
SM
1239 (push (list (list temp (pop cl--loop-args))) cl--loop-bindings)
1240 (push `(>= (setq ,temp (1- ,temp)) 0) cl--loop-body)))
fcd73769 1241
ae1aa776 1242 ((memq word '(collect collecting))
4dd1c416
SM
1243 (let ((what (pop cl--loop-args))
1244 (var (cl--loop-handle-accum nil 'nreverse)))
1245 (if (eq var cl--loop-accum-var)
1246 (push `(progn (push ,what ,var) t) cl--loop-body)
03fef3e6
SM
1247 (push `(progn
1248 (setq ,var (nconc ,var (list ,what)))
4dd1c416 1249 t) cl--loop-body))))
fcd73769
RS
1250
1251 ((memq word '(nconc nconcing append appending))
4dd1c416
SM
1252 (let ((what (pop cl--loop-args))
1253 (var (cl--loop-handle-accum nil 'nreverse)))
03fef3e6
SM
1254 (push `(progn
1255 (setq ,var
4dd1c416 1256 ,(if (eq var cl--loop-accum-var)
03fef3e6
SM
1257 `(nconc
1258 (,(if (memq word '(nconc nconcing))
1259 #'nreverse #'reverse)
1260 ,what)
1261 ,var)
1262 `(,(if (memq word '(nconc nconcing))
1263 #'nconc #'append)
4dd1c416 1264 ,var ,what))) t) cl--loop-body)))
fcd73769
RS
1265
1266 ((memq word '(concat concating))
4dd1c416
SM
1267 (let ((what (pop cl--loop-args))
1268 (var (cl--loop-handle-accum "")))
1269 (push `(progn (cl-callf concat ,var ,what) t) cl--loop-body)))
fcd73769
RS
1270
1271 ((memq word '(vconcat vconcating))
4dd1c416
SM
1272 (let ((what (pop cl--loop-args))
1273 (var (cl--loop-handle-accum [])))
1274 (push `(progn (cl-callf vconcat ,var ,what) t) cl--loop-body)))
fcd73769
RS
1275
1276 ((memq word '(sum summing))
4dd1c416
SM
1277 (let ((what (pop cl--loop-args))
1278 (var (cl--loop-handle-accum 0)))
1279 (push `(progn (cl-incf ,var ,what) t) cl--loop-body)))
fcd73769
RS
1280
1281 ((memq word '(count counting))
4dd1c416
SM
1282 (let ((what (pop cl--loop-args))
1283 (var (cl--loop-handle-accum 0)))
1284 (push `(progn (if ,what (cl-incf ,var)) t) cl--loop-body)))
fcd73769
RS
1285
1286 ((memq word '(minimize minimizing maximize maximizing))
4dd1c416
SM
1287 (let* ((what (pop cl--loop-args))
1288 (temp (if (cl--simple-expr-p what) what (make-symbol "--cl-var--")))
1289 (var (cl--loop-handle-accum nil))
fcd73769 1290 (func (intern (substring (symbol-name word) 0 3)))
03fef3e6
SM
1291 (set `(setq ,var (if ,var (,func ,var ,temp) ,temp))))
1292 (push `(progn ,(if (eq temp what) set
1293 `(let ((,temp ,what)) ,set))
4dd1c416 1294 t) cl--loop-body)))
fcd73769
RS
1295
1296 ((eq word 'with)
1297 (let ((bindings nil))
4dd1c416
SM
1298 (while (progn (push (list (pop cl--loop-args)
1299 (and (eq (car cl--loop-args) '=) (cl-pop2 cl--loop-args)))
e542ea4b 1300 bindings)
4dd1c416
SM
1301 (eq (car cl--loop-args) 'and))
1302 (pop cl--loop-args))
1303 (push (nreverse bindings) cl--loop-bindings)))
fcd73769
RS
1304
1305 ((eq word 'while)
4dd1c416 1306 (push (pop cl--loop-args) cl--loop-body))
fcd73769
RS
1307
1308 ((eq word 'until)
4dd1c416 1309 (push `(not ,(pop cl--loop-args)) cl--loop-body))
fcd73769
RS
1310
1311 ((eq word 'always)
4dd1c416
SM
1312 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1313 (push `(setq ,cl--loop-finish-flag ,(pop cl--loop-args)) cl--loop-body)
1314 (setq cl--loop-result t))
fcd73769
RS
1315
1316 ((eq word 'never)
4dd1c416
SM
1317 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1318 (push `(setq ,cl--loop-finish-flag (not ,(pop cl--loop-args)))
1319 cl--loop-body)
1320 (setq cl--loop-result t))
fcd73769
RS
1321
1322 ((eq word 'thereis)
4dd1c416
SM
1323 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1324 (or cl--loop-result-var (setq cl--loop-result-var (make-symbol "--cl-var--")))
1325 (push `(setq ,cl--loop-finish-flag
1326 (not (setq ,cl--loop-result-var ,(pop cl--loop-args))))
1327 cl--loop-body))
fcd73769
RS
1328
1329 ((memq word '(if when unless))
4dd1c416
SM
1330 (let* ((cond (pop cl--loop-args))
1331 (then (let ((cl--loop-body nil))
fcd73769 1332 (cl-parse-loop-clause)
4dd1c416
SM
1333 (cl--loop-build-ands (nreverse cl--loop-body))))
1334 (else (let ((cl--loop-body nil))
1335 (if (eq (car cl--loop-args) 'else)
1336 (progn (pop cl--loop-args) (cl-parse-loop-clause)))
1337 (cl--loop-build-ands (nreverse cl--loop-body))))
fcd73769 1338 (simple (and (eq (car then) t) (eq (car else) t))))
4dd1c416 1339 (if (eq (car cl--loop-args) 'end) (pop cl--loop-args))
fcd73769
RS
1340 (if (eq word 'unless) (setq then (prog1 else (setq else then))))
1341 (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then))
1342 (if simple (nth 1 else) (list (nth 2 else))))))
4dd1c416 1343 (if (cl--expr-contains form 'it)
e542ea4b 1344 (let ((temp (make-symbol "--cl-var--")))
4dd1c416 1345 (push (list temp) cl--loop-bindings)
03fef3e6 1346 (setq form `(if (setq ,temp ,cond)
7c1898a7 1347 ,@(cl-subst temp 'it form))))
03fef3e6 1348 (setq form `(if ,cond ,@form)))
4dd1c416 1349 (push (if simple `(progn ,form t) form) cl--loop-body))))
fcd73769
RS
1350
1351 ((memq word '(do doing))
1352 (let ((body nil))
4dd1c416
SM
1353 (or (consp (car cl--loop-args)) (error "Syntax error on `do' clause"))
1354 (while (consp (car cl--loop-args)) (push (pop cl--loop-args) body))
1355 (push (cons 'progn (nreverse (cons t body))) cl--loop-body)))
fcd73769
RS
1356
1357 ((eq word 'return)
4dd1c416
SM
1358 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-var--")))
1359 (or cl--loop-result-var (setq cl--loop-result-var (make-symbol "--cl-var--")))
1360 (push `(setq ,cl--loop-result-var ,(pop cl--loop-args)
1361 ,cl--loop-finish-flag nil) cl--loop-body))
fcd73769
RS
1362
1363 (t
4dd1c416 1364 (let ((handler (and (symbolp word) (get word 'cl--loop-handler))))
7c1898a7 1365 (or handler (error "Expected a cl-loop keyword, found %s" word))
fcd73769 1366 (funcall handler))))
4dd1c416
SM
1367 (if (eq (car cl--loop-args) 'and)
1368 (progn (pop cl--loop-args) (cl-parse-loop-clause)))))
fcd73769 1369
4dd1c416 1370(defun cl--loop-let (specs body par) ; uses loop-*
fcd73769 1371 (let ((p specs) (temps nil) (new nil))
7c1898a7 1372 (while (and p (or (symbolp (car-safe (car p))) (null (cl-cadar p))))
fcd73769
RS
1373 (setq p (cdr p)))
1374 (and par p
1375 (progn
1376 (setq par nil p specs)
1377 (while p
4dd1c416 1378 (or (macroexp-const-p (cl-cadar p))
e542ea4b 1379 (let ((temp (make-symbol "--cl-var--")))
7c1898a7 1380 (push (list temp (cl-cadar p)) temps)
fcd73769
RS
1381 (setcar (cdar p) temp)))
1382 (setq p (cdr p)))))
1383 (while specs
1384 (if (and (consp (car specs)) (listp (caar specs)))
1385 (let* ((spec (caar specs)) (nspecs nil)
69d8fb1e 1386 (expr (cadr (pop specs)))
4dd1c416 1387 (temp (cdr (or (assq spec cl--loop-destr-temps)
69d8fb1e 1388 (car (push (cons spec (or (last spec 0)
e542ea4b 1389 (make-symbol "--cl-var--")))
4dd1c416 1390 cl--loop-destr-temps))))))
69d8fb1e 1391 (push (list temp expr) new)
fcd73769 1392 (while (consp spec)
69d8fb1e 1393 (push (list (pop spec)
fcd73769
RS
1394 (and expr (list (if spec 'pop 'car) temp)))
1395 nspecs))
1396 (setq specs (nconc (nreverse nspecs) specs)))
69d8fb1e 1397 (push (pop specs) new)))
fcd73769 1398 (if (eq body 'setq)
7c1898a7 1399 (let ((set (cons (if par 'cl-psetq 'setq) (apply 'nconc (nreverse new)))))
03fef3e6
SM
1400 (if temps `(let* ,(nreverse temps) ,set) set))
1401 `(,(if par 'let 'let*)
1402 ,(nconc (nreverse temps) (nreverse new)) ,@body))))
fcd73769 1403
4dd1c416
SM
1404(defun cl--loop-handle-accum (def &optional func) ; uses loop-*
1405 (if (eq (car cl--loop-args) 'into)
1406 (let ((var (cl-pop2 cl--loop-args)))
1407 (or (memq var cl--loop-accum-vars)
1408 (progn (push (list (list var def)) cl--loop-bindings)
1409 (push var cl--loop-accum-vars)))
fcd73769 1410 var)
4dd1c416 1411 (or cl--loop-accum-var
fcd73769 1412 (progn
4dd1c416
SM
1413 (push (list (list (setq cl--loop-accum-var (make-symbol "--cl-var--")) def))
1414 cl--loop-bindings)
1415 (setq cl--loop-result (if func (list func cl--loop-accum-var)
1416 cl--loop-accum-var))
1417 cl--loop-accum-var))))
fcd73769 1418
4dd1c416 1419(defun cl--loop-build-ands (clauses)
fcd73769
RS
1420 (let ((ands nil)
1421 (body nil))
1422 (while clauses
1423 (if (and (eq (car-safe (car clauses)) 'progn)
1424 (eq (car (last (car clauses))) t))
1425 (if (cdr clauses)
1426 (setq clauses (cons (nconc (butlast (car clauses))
1427 (if (eq (car-safe (cadr clauses))
1428 'progn)
7c1898a7 1429 (cl-cdadr clauses)
fcd73769
RS
1430 (list (cadr clauses))))
1431 (cddr clauses)))
69d8fb1e
SM
1432 (setq body (cdr (butlast (pop clauses)))))
1433 (push (pop clauses) ands)))
fcd73769
RS
1434 (setq ands (or (nreverse ands) (list t)))
1435 (list (if (cdr ands) (cons 'and ands) (car ands))
1436 body
1437 (let ((full (if body
1438 (append ands (list (cons 'progn (append body '(t)))))
1439 ands)))
1440 (if (cdr full) (cons 'and full) (car full))))))
1441
1442
1443;;; Other iteration control structures.
1444
ebacfcc6 1445;;;###autoload
7c1898a7
SM
1446(defmacro cl-do (steps endtest &rest body)
1447 "The Common Lisp `cl-do' loop.
a766dfa1
JB
1448
1449\(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
70b8ef8f
SM
1450 (declare (indent 2)
1451 (debug
b1198e17
SM
1452 ((&rest &or symbolp (symbolp &optional form form))
1453 (form body)
1454 cl-declarations body)))
fcd73769
RS
1455 (cl-expand-do-loop steps endtest body nil))
1456
ebacfcc6 1457;;;###autoload
7c1898a7
SM
1458(defmacro cl-do* (steps endtest &rest body)
1459 "The Common Lisp `cl-do*' loop.
a766dfa1
JB
1460
1461\(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
7c1898a7 1462 (declare (indent 2) (debug cl-do))
fcd73769
RS
1463 (cl-expand-do-loop steps endtest body t))
1464
1465(defun cl-expand-do-loop (steps endtest body star)
7c1898a7 1466 `(cl-block nil
03fef3e6
SM
1467 (,(if star 'let* 'let)
1468 ,(mapcar (lambda (c) (if (consp c) (list (car c) (nth 1 c)) c))
1469 steps)
1470 (while (not ,(car endtest))
1471 ,@body
1472 ,@(let ((sets (mapcar (lambda (c)
1473 (and (consp c) (cdr (cdr c))
1474 (list (car c) (nth 2 c))))
1475 steps)))
1476 (setq sets (delq nil sets))
1477 (and sets
1478 (list (cons (if (or star (not (cdr sets)))
7c1898a7 1479 'setq 'cl-psetq)
03fef3e6
SM
1480 (apply 'append sets))))))
1481 ,@(or (cdr endtest) '(nil)))))
fcd73769 1482
ebacfcc6 1483;;;###autoload
7c1898a7 1484(defmacro cl-dolist (spec &rest body)
69d8fb1e 1485 "Loop over a list.
63744c0f 1486Evaluate BODY with VAR bound to each `car' from LIST, in turn.
69d8fb1e 1487Then evaluate RESULT to get return value, default nil.
ce887515 1488An implicit nil block is established around the loop.
69d8fb1e
SM
1489
1490\(fn (VAR LIST [RESULT]) BODY...)"
b1198e17 1491 (declare (debug ((symbolp form &optional form) cl-declarations body)))
e542ea4b 1492 (let ((temp (make-symbol "--cl-dolist-temp--")))
2462470b 1493 ;; FIXME: Copy&pasted from subr.el.
7c1898a7 1494 `(cl-block nil
2462470b
SM
1495 ;; This is not a reliable test, but it does not matter because both
1496 ;; semantics are acceptable, tho one is slightly faster with dynamic
1497 ;; scoping and the other is slightly faster (and has cleaner semantics)
1498 ;; with lexical scoping.
1499 ,(if lexical-binding
1500 `(let ((,temp ,(nth 1 spec)))
1501 (while ,temp
1502 (let ((,(car spec) (car ,temp)))
1503 ,@body
1504 (setq ,temp (cdr ,temp))))
1505 ,@(if (cdr (cdr spec))
1506 ;; FIXME: This let often leads to "unused var" warnings.
1507 `((let ((,(car spec) nil)) ,@(cdr (cdr spec))))))
1508 `(let ((,temp ,(nth 1 spec))
1509 ,(car spec))
1510 (while ,temp
1511 (setq ,(car spec) (car ,temp))
1512 ,@body
1513 (setq ,temp (cdr ,temp)))
1514 ,@(if (cdr (cdr spec))
1515 `((setq ,(car spec) nil) ,@(cddr spec))))))))
63744c0f 1516
ebacfcc6 1517;;;###autoload
7c1898a7 1518(defmacro cl-dotimes (spec &rest body)
69d8fb1e 1519 "Loop a certain number of times.
63744c0f
DL
1520Evaluate BODY with VAR bound to successive integers from 0, inclusive,
1521to COUNT, exclusive. Then evaluate RESULT to get return value, default
69d8fb1e
SM
1522nil.
1523
1524\(fn (VAR COUNT [RESULT]) BODY...)"
7c1898a7 1525 (declare (debug cl-dolist))
2462470b
SM
1526 (let ((temp (make-symbol "--cl-dotimes-temp--"))
1527 (end (nth 1 spec)))
1528 ;; FIXME: Copy&pasted from subr.el.
7c1898a7 1529 `(cl-block nil
2462470b
SM
1530 ;; This is not a reliable test, but it does not matter because both
1531 ;; semantics are acceptable, tho one is slightly faster with dynamic
1532 ;; scoping and the other has cleaner semantics.
1533 ,(if lexical-binding
1534 (let ((counter '--dotimes-counter--))
1535 `(let ((,temp ,end)
1536 (,counter 0))
1537 (while (< ,counter ,temp)
1538 (let ((,(car spec) ,counter))
1539 ,@body)
1540 (setq ,counter (1+ ,counter)))
1541 ,@(if (cddr spec)
1542 ;; FIXME: This let often leads to "unused var" warnings.
1543 `((let ((,(car spec) ,counter)) ,@(cddr spec))))))
1544 `(let ((,temp ,end)
1545 (,(car spec) 0))
1546 (while (< ,(car spec) ,temp)
1547 ,@body
7c1898a7 1548 (cl-incf ,(car spec)))
2462470b 1549 ,@(cdr (cdr spec)))))))
63744c0f 1550
ebacfcc6 1551;;;###autoload
7c1898a7 1552(defmacro cl-do-symbols (spec &rest body)
69d8fb1e 1553 "Loop over all symbols.
fcd73769 1554Evaluate BODY with VAR bound to each interned symbol, or to each symbol
69d8fb1e
SM
1555from OBARRAY.
1556
1557\(fn (VAR [OBARRAY [RESULT]]) BODY...)"
70b8ef8f
SM
1558 (declare (indent 1)
1559 (debug ((symbolp &optional form form) cl-declarations body)))
fcd73769 1560 ;; Apparently this doesn't have an implicit block.
7c1898a7 1561 `(cl-block nil
03fef3e6
SM
1562 (let (,(car spec))
1563 (mapatoms #'(lambda (,(car spec)) ,@body)
1564 ,@(and (cadr spec) (list (cadr spec))))
7c1898a7 1565 ,(cl-caddr spec))))
fcd73769 1566
ebacfcc6 1567;;;###autoload
7c1898a7 1568(defmacro cl-do-all-symbols (spec &rest body)
70b8ef8f 1569 (declare (indent 1) (debug ((symbolp &optional form) cl-declarations body)))
7c1898a7 1570 `(cl-do-symbols (,(car spec) nil ,(cadr spec)) ,@body))
fcd73769
RS
1571
1572
1573;;; Assignments.
1574
ebacfcc6 1575;;;###autoload
7c1898a7 1576(defmacro cl-psetq (&rest args)
69d8fb1e 1577 "Set SYMs to the values VALs in parallel.
fcd73769 1578This is like `setq', except that all VAL forms are evaluated (in order)
69d8fb1e
SM
1579before assigning any symbols SYM to the corresponding values.
1580
1581\(fn SYM VAL SYM VAL ...)"
b1198e17 1582 (declare (debug setq))
7c1898a7 1583 (cons 'cl-psetf args))
fcd73769
RS
1584
1585
1586;;; Binding control structures.
1587
ebacfcc6 1588;;;###autoload
7c1898a7 1589(defmacro cl-progv (symbols values &rest body)
64a4c526 1590 "Bind SYMBOLS to VALUES dynamically in BODY.
fcd73769 1591The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists.
3187ba1c 1592Each symbol in the first list is bound to the corresponding value in the
fcd73769
RS
1593second list (or made unbound if VALUES is shorter than SYMBOLS); then the
1594BODY forms are executed and their result is returned. This is much like
1595a `let' form, except that the list of symbols can be computed at run-time."
70b8ef8f 1596 (declare (indent 2) (debug (form form body)))
bb3faf5b 1597 `(let ((cl--progv-save nil))
03fef3e6 1598 (unwind-protect
bb3faf5b
SM
1599 (progn (cl--progv-before ,symbols ,values) ,@body)
1600 (cl--progv-after))))
fcd73769 1601
de7e2b36
SM
1602(defvar cl--labels-convert-cache nil)
1603
1604(defun cl--labels-convert (f)
1605 "Special macro-expander to rename (function F) references in `cl-labels'."
1606 (cond
1607 ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
1608 ;; *after* handling `function', but we want to stop macroexpansion from
1609 ;; being applied infinitely, so we use a cache to return the exact `form'
1610 ;; being expanded even though we don't receive it.
1611 ((eq f (car cl--labels-convert-cache)) (cdr cl--labels-convert-cache))
1612 (t
1613 (let ((found (assq f macroexpand-all-environment)))
1614 (if (and found (ignore-errors
1615 (eq (cadr (cl-caddr found)) 'cl-labels-args)))
1616 (cadr (cl-caddr (cl-cadddr found)))
1617 (let ((res `(function ,f)))
1618 (setq cl--labels-convert-cache (cons f res))
1619 res))))))
1620
fcd73769 1621;;; This should really have some way to shadow 'byte-compile properties, etc.
ebacfcc6 1622;;;###autoload
7c1898a7 1623(defmacro cl-flet (bindings &rest body)
3187ba1c 1624 "Make temporary function definitions.
de7e2b36 1625Like `cl-labels' but the definitions are not recursive.
69d8fb1e
SM
1626
1627\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
7c1898a7 1628 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body)))
de7e2b36
SM
1629 (let ((binds ()) (newenv macroexpand-all-environment))
1630 (dolist (binding bindings)
1631 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1632 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1633 (push (cons (car binding)
1634 `(lambda (&rest cl-labels-args)
1635 (cl-list* 'funcall ',var
1636 cl-labels-args)))
1637 newenv)))
1638 `(let ,(nreverse binds)
1639 ,@(macroexp-unprogn
1640 (macroexpand-all
1641 `(progn ,@body)
1642 ;; Don't override lexical-let's macro-expander.
1643 (if (assq 'function newenv) newenv
1644 (cons (cons 'function #'cl--labels-convert) newenv)))))))
fcd73769 1645
ebacfcc6 1646;;;###autoload
7c1898a7 1647(defmacro cl-labels (bindings &rest body)
3187ba1c 1648 "Make temporary function bindings.
de7e2b36 1649The bindings can be recursive. Assumes the use of `lexical-binding'.
69d8fb1e
SM
1650
1651\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
7c1898a7 1652 (declare (indent 1) (debug cl-flet))
de7e2b36
SM
1653 (let ((binds ()) (newenv macroexpand-all-environment))
1654 (dolist (binding bindings)
1655 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1656 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1657 (push (cons (car binding)
4dd1c416
SM
1658 `(lambda (&rest cl-labels-args)
1659 (cl-list* 'funcall ',var
1660 cl-labels-args)))
6fa6c4ae 1661 newenv)))
de7e2b36
SM
1662 (macroexpand-all `(letrec ,(nreverse binds) ,@body)
1663 ;; Don't override lexical-let's macro-expander.
1664 (if (assq 'function newenv) newenv
1665 (cons (cons 'function #'cl--labels-convert) newenv)))))
fcd73769
RS
1666
1667;; The following ought to have a better definition for use with newer
1668;; byte compilers.
ebacfcc6 1669;;;###autoload
7c1898a7 1670(defmacro cl-macrolet (bindings &rest body)
4342e957 1671 "Make temporary macro definitions.
7c1898a7 1672This is like `cl-flet', but for macros instead of functions.
69d8fb1e
SM
1673
1674\(fn ((NAME ARGLIST BODY...) ...) FORM...)"
70b8ef8f
SM
1675 (declare (indent 1)
1676 (debug
b1198e17
SM
1677 ((&rest (&define name (&rest arg) cl-declarations-or-string
1678 def-body))
1679 cl-declarations body)))
fcd73769 1680 (if (cdr bindings)
7c1898a7 1681 `(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
fcd73769
RS
1682 (if (null bindings) (cons 'progn body)
1683 (let* ((name (caar bindings))
4dd1c416 1684 (res (cl--transform-lambda (cdar bindings) name)))
fcd73769 1685 (eval (car res))
6fa6c4ae
SM
1686 (macroexpand-all (cons 'progn body)
1687 (cons (cons name `(lambda ,@(cdr res)))
1688 macroexpand-all-environment))))))
1689
1690(defconst cl--old-macroexpand
1691 (if (and (boundp 'cl--old-macroexpand)
1692 (eq (symbol-function 'macroexpand)
1693 #'cl--sm-macroexpand))
1694 cl--old-macroexpand
1695 (symbol-function 'macroexpand)))
1696
1697(defun cl--sm-macroexpand (cl-macro &optional cl-env)
1698 "Special macro expander used inside `cl-symbol-macrolet'.
1699This function replaces `macroexpand' during macro expansion
1700of `cl-symbol-macrolet', and does the same thing as `macroexpand'
1701except that it additionally expands symbol macros."
1702 (let ((macroexpand-all-environment cl-env))
1703 (while
1704 (progn
1705 (setq cl-macro (funcall cl--old-macroexpand cl-macro cl-env))
1706 (cond
1707 ((symbolp cl-macro)
1708 ;; Perform symbol-macro expansion.
1709 (when (cdr (assq (symbol-name cl-macro) cl-env))
1710 (setq cl-macro (cadr (assq (symbol-name cl-macro) cl-env)))))
1711 ((eq 'setq (car-safe cl-macro))
2ee3d7f0 1712 ;; Convert setq to setf if required by symbol-macro expansion.
6fa6c4ae
SM
1713 (let* ((args (mapcar (lambda (f) (cl--sm-macroexpand f cl-env))
1714 (cdr cl-macro)))
1715 (p args))
1716 (while (and p (symbolp (car p))) (setq p (cddr p)))
2ee3d7f0 1717 (if p (setq cl-macro (cons 'setf args))
6fa6c4ae
SM
1718 (setq cl-macro (cons 'setq args))
1719 ;; Don't loop further.
1720 nil))))))
1721 cl-macro))
fcd73769 1722
ebacfcc6 1723;;;###autoload
7c1898a7 1724(defmacro cl-symbol-macrolet (bindings &rest body)
4342e957 1725 "Make symbol macro definitions.
fcd73769 1726Within the body FORMs, references to the variable NAME will be replaced
2ee3d7f0 1727by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
69d8fb1e
SM
1728
1729\(fn ((NAME EXPANSION) ...) FORM...)"
70b8ef8f 1730 (declare (indent 1) (debug ((&rest (symbol sexp)) cl-declarations body)))
6fa6c4ae
SM
1731 (cond
1732 ((cdr bindings)
7c1898a7 1733 `(cl-symbol-macrolet (,(car bindings))
6fa6c4ae
SM
1734 (cl-symbol-macrolet ,(cdr bindings) ,@body)))
1735 ((null bindings) (macroexp-progn body))
1736 (t
1737 (let ((previous-macroexpand (symbol-function 'macroexpand)))
1738 (unwind-protect
1739 (progn
1740 (fset 'macroexpand #'cl--sm-macroexpand)
1741 ;; FIXME: For N bindings, this will traverse `body' N times!
1742 (macroexpand-all (cons 'progn body)
fcd73769 1743 (cons (list (symbol-name (caar bindings))
7c1898a7 1744 (cl-cadar bindings))
6fa6c4ae
SM
1745 macroexpand-all-environment)))
1746 (fset 'macroexpand previous-macroexpand))))))
fcd73769 1747
fcd73769
RS
1748;;; Multiple values.
1749
ebacfcc6 1750;;;###autoload
7c1898a7 1751(defmacro cl-multiple-value-bind (vars form &rest body)
69d8fb1e 1752 "Collect multiple return values.
fcd73769
RS
1753FORM must return a list; the BODY is then executed with the first N elements
1754of this list bound (`let'-style) to each of the symbols SYM in turn. This
7c1898a7
SM
1755is analogous to the Common Lisp `cl-multiple-value-bind' macro, using lists to
1756simulate true multiple return values. For compatibility, (cl-values A B C) is
69d8fb1e
SM
1757a synonym for (list A B C).
1758
3187ba1c 1759\(fn (SYM...) FORM BODY)"
70b8ef8f 1760 (declare (indent 2) (debug ((&rest symbolp) form body)))
e542ea4b 1761 (let ((temp (make-symbol "--cl-var--")) (n -1))
03fef3e6
SM
1762 `(let* ((,temp ,form)
1763 ,@(mapcar (lambda (v)
1764 (list v `(nth ,(setq n (1+ n)) ,temp)))
1765 vars))
1766 ,@body)))
fcd73769 1767
ebacfcc6 1768;;;###autoload
7c1898a7 1769(defmacro cl-multiple-value-setq (vars form)
69d8fb1e 1770 "Collect multiple return values.
fcd73769
RS
1771FORM must return a list; the first N elements of this list are stored in
1772each of the symbols SYM in turn. This is analogous to the Common Lisp
7c1898a7
SM
1773`cl-multiple-value-setq' macro, using lists to simulate true multiple return
1774values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
69d8fb1e 1775
3187ba1c 1776\(fn (SYM...) FORM)"
70b8ef8f 1777 (declare (indent 1) (debug ((&rest symbolp) form)))
03fef3e6
SM
1778 (cond ((null vars) `(progn ,form nil))
1779 ((null (cdr vars)) `(setq ,(car vars) (car ,form)))
fcd73769 1780 (t
e542ea4b 1781 (let* ((temp (make-symbol "--cl-var--")) (n 0))
03fef3e6
SM
1782 `(let ((,temp ,form))
1783 (prog1 (setq ,(pop vars) (car ,temp))
1784 (setq ,@(apply #'nconc
1785 (mapcar (lambda (v)
1786 (list v `(nth ,(setq n (1+ n))
1787 ,temp)))
1788 vars)))))))))
fcd73769
RS
1789
1790
1791;;; Declarations.
1792
ebacfcc6 1793;;;###autoload
7c1898a7 1794(defmacro cl-locally (&rest body)
b1198e17
SM
1795 (declare (debug t))
1796 (cons 'progn body))
ebacfcc6 1797;;;###autoload
513749ee 1798(defmacro cl-the (_type form)
70b8ef8f 1799 (declare (indent 1) (debug (cl-type-spec form)))
b1198e17 1800 form)
fcd73769
RS
1801
1802(defvar cl-proclaim-history t) ; for future compilers
1803(defvar cl-declare-stack t) ; for future compilers
1804
1805(defun cl-do-proclaim (spec hist)
69d8fb1e 1806 (and hist (listp cl-proclaim-history) (push spec cl-proclaim-history))
fcd73769
RS
1807 (cond ((eq (car-safe spec) 'special)
1808 (if (boundp 'byte-compile-bound-variables)
1809 (setq byte-compile-bound-variables
1810 (append (cdr spec) byte-compile-bound-variables))))
1811
1812 ((eq (car-safe spec) 'inline)
1813 (while (setq spec (cdr spec))
1814 (or (memq (get (car spec) 'byte-optimizer)
1815 '(nil byte-compile-inline-expand))
1816 (error "%s already has a byte-optimizer, can't make it inline"
1817 (car spec)))
1818 (put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
1819
1820 ((eq (car-safe spec) 'notinline)
1821 (while (setq spec (cdr spec))
1822 (if (eq (get (car spec) 'byte-optimizer)
1823 'byte-compile-inline-expand)
1824 (put (car spec) 'byte-optimizer nil))))
1825
1826 ((eq (car-safe spec) 'optimize)
1827 (let ((speed (assq (nth 1 (assq 'speed (cdr spec)))
1828 '((0 nil) (1 t) (2 t) (3 t))))
1829 (safety (assq (nth 1 (assq 'safety (cdr spec)))
1830 '((0 t) (1 t) (2 t) (3 nil)))))
1831 (if speed (setq cl-optimize-speed (car speed)
1832 byte-optimize (nth 1 speed)))
1833 (if safety (setq cl-optimize-safety (car safety)
1834 byte-compile-delete-errors (nth 1 safety)))))
1835
1836 ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings))
fcd73769
RS
1837 (while (setq spec (cdr spec))
1838 (if (consp (car spec))
7c1898a7 1839 (if (eq (cl-cadar spec) 0)
bc8ce89b
GM
1840 (byte-compile-disable-warning (caar spec))
1841 (byte-compile-enable-warning (caar spec)))))))
fcd73769
RS
1842 nil)
1843
1844;;; Process any proclamations made before cl-macs was loaded.
1845(defvar cl-proclaims-deferred)
1846(let ((p (reverse cl-proclaims-deferred)))
69d8fb1e 1847 (while p (cl-do-proclaim (pop p) t))
fcd73769
RS
1848 (setq cl-proclaims-deferred nil))
1849
ebacfcc6 1850;;;###autoload
7c1898a7 1851(defmacro cl-declare (&rest specs)
c39da690 1852 "Declare SPECS about the current function while compiling.
4bf0979f
LMI
1853For instance
1854
7c1898a7 1855 \(cl-declare (warn 0))
4bf0979f 1856
dbc44fcd
LMI
1857will turn off byte-compile warnings in the function.
1858See Info node `(cl)Declarations' for details."
bb3faf5b 1859 (if (cl--compiling-file)
fcd73769 1860 (while specs
69d8fb1e
SM
1861 (if (listp cl-declare-stack) (push (car specs) cl-declare-stack))
1862 (cl-do-proclaim (pop specs) nil)))
fcd73769
RS
1863 nil)
1864
1865
1866
1867;;; Generalized variables.
1868
fcd73769 1869;;; Some standard place types from Common Lisp.
2ee3d7f0
SM
1870(gv-define-setter cl-get (store x y &optional d) `(put ,x ,y ,store))
1871(gv-define-setter cl-subseq (new seq start &optional end)
7c1898a7 1872 `(progn (cl-replace ,seq ,new :start1 ,start :end1 ,end) ,new))
fcd73769
RS
1873
1874;;; Various car/cdr aliases. Note that `cadr' is handled specially.
2ee3d7f0
SM
1875(gv-define-setter cl-fourth (store x) `(setcar (cl-cdddr ,x) ,store))
1876(gv-define-setter cl-fifth (store x) `(setcar (nthcdr 4 ,x) ,store))
1877(gv-define-setter cl-sixth (store x) `(setcar (nthcdr 5 ,x) ,store))
1878(gv-define-setter cl-seventh (store x) `(setcar (nthcdr 6 ,x) ,store))
1879(gv-define-setter cl-eighth (store x) `(setcar (nthcdr 7 ,x) ,store))
1880(gv-define-setter cl-ninth (store x) `(setcar (nthcdr 8 ,x) ,store))
1881(gv-define-setter cl-tenth (store x) `(setcar (nthcdr 9 ,x) ,store))
fcd73769
RS
1882
1883;;; Some more Emacs-related place types.
2ee3d7f0
SM
1884(gv-define-simple-setter buffer-file-name set-visited-file-name t)
1885(gv-define-setter buffer-modified-p (flag &optional buf)
03fef3e6
SM
1886 `(with-current-buffer ,buf
1887 (set-buffer-modified-p ,flag)))
2ee3d7f0
SM
1888(gv-define-simple-setter buffer-name rename-buffer t)
1889(gv-define-setter buffer-string (store)
03fef3e6 1890 `(progn (erase-buffer) (insert ,store)))
2ee3d7f0
SM
1891(gv-define-simple-setter buffer-substring cl--set-buffer-substring)
1892(gv-define-simple-setter current-buffer set-buffer)
1893(gv-define-simple-setter current-case-table set-case-table)
1894(gv-define-simple-setter current-column move-to-column t)
1895(gv-define-simple-setter current-global-map use-global-map t)
1896(gv-define-setter current-input-mode (store)
03fef3e6 1897 `(progn (apply #'set-input-mode ,store) ,store))
2ee3d7f0
SM
1898(gv-define-simple-setter current-local-map use-local-map t)
1899(gv-define-simple-setter current-window-configuration set-window-configuration t)
1900(gv-define-simple-setter default-file-modes set-default-file-modes t)
1901(gv-define-simple-setter documentation-property put)
1902(gv-define-setter face-background (x f &optional s) `(set-face-background ,f ,x ,s))
1903(gv-define-setter face-background-pixmap (x f &optional s)
03fef3e6 1904 `(set-face-background-pixmap ,f ,x ,s))
2ee3d7f0
SM
1905(gv-define-setter face-font (x f &optional s) `(set-face-font ,f ,x ,s))
1906(gv-define-setter face-foreground (x f &optional s) `(set-face-foreground ,f ,x ,s))
1907(gv-define-setter face-underline-p (x f &optional s)
03fef3e6 1908 `(set-face-underline-p ,f ,x ,s))
2ee3d7f0
SM
1909(gv-define-simple-setter file-modes set-file-modes t)
1910(gv-define-simple-setter frame-height set-screen-height t)
1911(gv-define-simple-setter frame-parameters modify-frame-parameters t)
1912(gv-define-simple-setter frame-visible-p cl--set-frame-visible-p)
1913(gv-define-simple-setter frame-width set-screen-width t)
1914(gv-define-simple-setter getenv setenv t)
1915(gv-define-simple-setter get-register set-register)
1916(gv-define-simple-setter global-key-binding global-set-key)
1917(gv-define-simple-setter local-key-binding local-set-key)
1918(gv-define-simple-setter mark set-mark t)
1919(gv-define-simple-setter mark-marker set-mark t)
1920(gv-define-simple-setter marker-position set-marker t)
1921(gv-define-setter mouse-position (store scr)
03fef3e6
SM
1922 `(set-mouse-position ,scr (car ,store) (cadr ,store)
1923 (cddr ,store)))
2ee3d7f0
SM
1924(gv-define-simple-setter point goto-char)
1925(gv-define-simple-setter point-marker goto-char t)
1926(gv-define-setter point-max (store)
03fef3e6 1927 `(progn (narrow-to-region (point-min) ,store) ,store))
2ee3d7f0 1928(gv-define-setter point-min (store)
03fef3e6 1929 `(progn (narrow-to-region ,store (point-max)) ,store))
2ee3d7f0 1930(gv-define-setter read-mouse-position (store scr)
03fef3e6 1931 `(set-mouse-position ,scr (car ,store) (cdr ,store)))
2ee3d7f0
SM
1932(gv-define-simple-setter screen-height set-screen-height t)
1933(gv-define-simple-setter screen-width set-screen-width t)
1934(gv-define-simple-setter selected-window select-window)
1935(gv-define-simple-setter selected-screen select-screen)
1936(gv-define-simple-setter selected-frame select-frame)
1937(gv-define-simple-setter standard-case-table set-standard-case-table)
1938(gv-define-simple-setter syntax-table set-syntax-table)
1939(gv-define-simple-setter visited-file-modtime set-visited-file-modtime t)
1940(gv-define-setter window-height (store)
03fef3e6 1941 `(progn (enlarge-window (- ,store (window-height))) ,store))
2ee3d7f0 1942(gv-define-setter window-width (store)
03fef3e6 1943 `(progn (enlarge-window (- ,store (window-width)) t) ,store))
2ee3d7f0
SM
1944(gv-define-simple-setter x-get-secondary-selection x-own-secondary-selection t)
1945(gv-define-simple-setter x-get-selection x-own-selection t)
fcd73769 1946
2ee3d7f0
SM
1947;;; More complex setf-methods.
1948
1949;; This is a hack that allows (setf (eq a 7) B) to mean either
f44379e7
SM
1950;; (setq a 7) or (setq a nil) depending on whether B is nil or not.
1951;; This is useful when you have control over the PLACE but not over
1952;; the VALUE, as is the case in define-minor-mode's :variable.
2ee3d7f0
SM
1953;; It turned out that :variable needed more flexibility anyway, so
1954;; this doesn't seem too useful now.
1955(gv-define-expander eq
1956 (lambda (do place val)
1957 (gv-letplace (getter setter) place
1958 (macroexp-let2 nil val val
1959 (funcall do `(eq ,getter ,val)
1960 (lambda (v)
1961 `(cond
1962 (,v ,(funcall setter val))
1963 ((eq ,getter ,val) ,(funcall setter `(not ,val))))))))))
1964
1965(gv-define-expander nthcdr
1966 (lambda (do n place)
1967 (macroexp-let2 nil idx n
1968 (gv-letplace (getter setter) place
1969 (funcall do `(nthcdr ,idx ,getter)
1970 (lambda (v) `(if (<= ,idx 0) ,(funcall setter v)
1971 (setcdr (nthcdr (1- ,idx) ,getter) ,v))))))))
1972
1973(gv-define-expander cl-getf
1974 (lambda (do place tag &optional def)
1975 (gv-letplace (getter setter) place
1976 (macroexp-let2 nil k tag
1977 (macroexp-let2 nil d def
1978 (funcall do `(cl-getf ,getter ,k ,d)
1979 (lambda (v) (funcall setter `(cl--set-getf ,getter ,k ,v)))))))))
1980
1981(gv-define-expander substring
1982 (lambda (do place from &optional to)
1983 (gv-letplace (getter setter) place
1984 (macroexp-let2 nil start from
1985 (macroexp-let2 nil end to
1986 (funcall do `(substring ,getter ,start ,end)
1987 (lambda (v)
1988 (funcall setter `(cl--set-substring
1989 ,getter ,start ,end ,v)))))))))
fcd73769
RS
1990
1991;;; The standard modify macros.
69d8fb1e 1992
2ee3d7f0 1993;; `setf' is now part of core Elisp, defined in gv.el.
fcd73769 1994
ebacfcc6 1995;;;###autoload
7c1898a7 1996(defmacro cl-psetf (&rest args)
69d8fb1e 1997 "Set PLACEs to the values VALs in parallel.
2ee3d7f0 1998This is like `setf', except that all VAL forms are evaluated (in order)
69d8fb1e
SM
1999before assigning any PLACEs to the corresponding values.
2000
2001\(fn PLACE VAL PLACE VAL ...)"
2ee3d7f0 2002 (declare (debug setf))
fcd73769
RS
2003 (let ((p args) (simple t) (vars nil))
2004 (while p
4dd1c416 2005 (if (or (not (symbolp (car p))) (cl--expr-depends-p (nth 1 p) vars))
fcd73769
RS
2006 (setq simple nil))
2007 (if (memq (car p) vars)
2008 (error "Destination duplicated in psetf: %s" (car p)))
69d8fb1e 2009 (push (pop p) vars)
7c1898a7 2010 (or p (error "Odd number of arguments to cl-psetf"))
69d8fb1e 2011 (pop p))
fcd73769 2012 (if simple
2ee3d7f0 2013 `(progn (setf ,@args) nil)
fcd73769 2014 (setq args (reverse args))
2ee3d7f0 2015 (let ((expr `(setf ,(cadr args) ,(car args))))
fcd73769 2016 (while (setq args (cddr args))
2ee3d7f0 2017 (setq expr `(setf ,(cadr args) (prog1 ,(car args) ,expr))))
03fef3e6 2018 `(progn ,expr nil)))))
fcd73769 2019
ebacfcc6 2020;;;###autoload
7c1898a7 2021(defmacro cl-remf (place tag)
64a4c526 2022 "Remove TAG from property list PLACE.
2ee3d7f0 2023PLACE may be a symbol, or any generalized variable allowed by `setf'.
fcd73769 2024The form returns true if TAG was found and removed, nil otherwise."
b1198e17 2025 (declare (debug (place form)))
2ee3d7f0
SM
2026 (gv-letplace (tval setter) place
2027 (macroexp-let2 macroexp-copyable-p ttag tag
2028 `(if (eq ,ttag (car ,tval))
2029 (progn ,(funcall setter `(cddr ,tval))
03fef3e6 2030 t)
ad4d226c 2031 (cl--do-remf ,tval ,ttag)))))
fcd73769 2032
ebacfcc6 2033;;;###autoload
7c1898a7 2034(defmacro cl-shiftf (place &rest args)
69d8fb1e 2035 "Shift left among PLACEs.
7c1898a7 2036Example: (cl-shiftf A B C) sets A to B, B to C, and returns the old A.
2ee3d7f0 2037Each PLACE may be a symbol, or any generalized variable allowed by `setf'.
69d8fb1e 2038
3187ba1c 2039\(fn PLACE... VAL)"
b1198e17 2040 (declare (debug (&rest place)))
2fa5eef4
SM
2041 (cond
2042 ((null args) place)
7c1898a7 2043 ((symbolp place) `(prog1 ,place (setq ,place (cl-shiftf ,@args))))
2fa5eef4 2044 (t
2ee3d7f0
SM
2045 (gv-letplace (getter setter) place
2046 `(prog1 ,getter
2047 ,(funcall setter `(cl-shiftf ,@args)))))))
fcd73769 2048
ebacfcc6 2049;;;###autoload
7c1898a7 2050(defmacro cl-rotatef (&rest args)
69d8fb1e 2051 "Rotate left among PLACEs.
7c1898a7 2052Example: (cl-rotatef A B C) sets A to B, B to C, and C to A. It returns nil.
2ee3d7f0 2053Each PLACE may be a symbol, or any generalized variable allowed by `setf'.
69d8fb1e
SM
2054
2055\(fn PLACE...)"
b1198e17 2056 (declare (debug (&rest place)))
fcd73769
RS
2057 (if (not (memq nil (mapcar 'symbolp args)))
2058 (and (cdr args)
2059 (let ((sets nil)
2060 (first (car args)))
2061 (while (cdr args)
69d8fb1e 2062 (setq sets (nconc sets (list (pop args) (car args)))))
7c1898a7 2063 `(cl-psetf ,@sets ,(car args) ,first)))
fcd73769 2064 (let* ((places (reverse args))
e542ea4b 2065 (temp (make-symbol "--cl-rotatef--"))
fcd73769
RS
2066 (form temp))
2067 (while (cdr places)
2ee3d7f0
SM
2068 (setq form
2069 (gv-letplace (getter setter) (pop places)
2070 `(prog1 ,getter ,(funcall setter form)))))
2071 (gv-letplace (getter setter) (car places)
2072 (macroexp-let* `((,temp ,getter))
2073 `(progn ,(funcall setter form) nil))))))
fcd73769 2074
ebacfcc6 2075;;;###autoload
7c1898a7 2076(defmacro cl-callf (func place &rest args)
69d8fb1e 2077 "Set PLACE to (FUNC PLACE ARGS...).
fcd73769 2078FUNC should be an unquoted function name. PLACE may be a symbol,
2ee3d7f0 2079or any generalized variable allowed by `setf'."
7c1898a7 2080 (declare (indent 2) (debug (cl-function place &rest form)))
2ee3d7f0
SM
2081 (gv-letplace (getter setter) place
2082 (let* ((rargs (cons getter args)))
2083 (funcall setter
2084 (if (symbolp func) (cons func rargs)
2085 `(funcall #',func ,@rargs))))))
fcd73769 2086
ebacfcc6 2087;;;###autoload
7c1898a7 2088(defmacro cl-callf2 (func arg1 place &rest args)
69d8fb1e 2089 "Set PLACE to (FUNC ARG1 PLACE ARGS...).
7c1898a7 2090Like `cl-callf', but PLACE is the second argument of FUNC, not the first.
69d8fb1e
SM
2091
2092\(fn FUNC ARG1 PLACE ARGS...)"
7c1898a7 2093 (declare (indent 3) (debug (cl-function form place &rest form)))
4dd1c416 2094 (if (and (cl--safe-expr-p arg1) (cl--simple-expr-p place) (symbolp func))
2ee3d7f0
SM
2095 `(setf ,place (,func ,arg1 ,place ,@args))
2096 (macroexp-let2 nil a1 arg1
2097 (gv-letplace (getter setter) place
2098 (let* ((rargs (cl-list* a1 getter args)))
2099 (funcall setter
2100 (if (symbolp func) (cons func rargs)
2101 `(funcall #',func ,@rargs))))))))
fcd73769
RS
2102
2103;;; Structures.
2104
ebacfcc6 2105;;;###autoload
7c1898a7 2106(defmacro cl-defstruct (struct &rest descs)
69d8fb1e 2107 "Define a struct type.
c7dc1ac1
CY
2108This macro defines a new data type called NAME that stores data
2109in SLOTs. It defines a `make-NAME' constructor, a `copy-NAME'
2110copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'.
2ee3d7f0 2111You can use the accessors to set the corresponding slots, via `setf'.
69d8fb1e 2112
c7dc1ac1
CY
2113NAME may instead take the form (NAME OPTIONS...), where each
2114OPTION is either a single keyword or (KEYWORD VALUE).
2115See Info node `(cl)Structures' for a list of valid keywords.
2116
2117Each SLOT may instead take the form (SLOT SLOT-OPTS...), where
2118SLOT-OPTS are keyword-value pairs for that slot. Currently, only
2119one keyword is supported, `:read-only'. If this has a non-nil
2ee3d7f0 2120value, that slot cannot be set via `setf'.
c7dc1ac1
CY
2121
2122\(fn NAME SLOTS...)"
b581bb5c
SM
2123 (declare (doc-string 2)
2124 (debug
b1198e17
SM
2125 (&define ;Makes top-level form not be wrapped.
2126 [&or symbolp
2127 (gate
2128 symbolp &rest
2129 (&or [":conc-name" symbolp]
2130 [":constructor" symbolp &optional cl-lambda-list]
2131 [":copier" symbolp]
2132 [":predicate" symbolp]
2133 [":include" symbolp &rest sexp] ;; Not finished.
2134 ;; The following are not supported.
2135 ;; [":print-function" ...]
2136 ;; [":type" ...]
2137 ;; [":initial-offset" ...]
2138 ))]
2139 [&optional stringp]
2140 ;; All the above is for the following def-form.
2141 &rest &or symbolp (symbolp def-form
2142 &optional ":read-only" sexp))))
fcd73769
RS
2143 (let* ((name (if (consp struct) (car struct) struct))
2144 (opts (cdr-safe struct))
2145 (slots nil)
2146 (defaults nil)
2147 (conc-name (concat (symbol-name name) "-"))
2148 (constructor (intern (format "make-%s" name)))
2149 (constrs nil)
2150 (copier (intern (format "copy-%s" name)))
2151 (predicate (intern (format "%s-p" name)))
2152 (print-func nil) (print-auto nil)
bb3faf5b 2153 (safety (if (cl--compiling-file) cl-optimize-safety 3))
fcd73769
RS
2154 (include nil)
2155 (tag (intern (format "cl-struct-%s" name)))
2156 (tag-symbol (intern (format "cl-struct-%s-tags" name)))
2157 (include-descs nil)
fcd73769
RS
2158 (side-eff nil)
2159 (type nil)
2160 (named nil)
2161 (forms nil)
2162 pred-form pred-check)
2163 (if (stringp (car descs))
03fef3e6
SM
2164 (push `(put ',name 'structure-documentation
2165 ,(pop descs)) forms))
fcd73769
RS
2166 (setq descs (cons '(cl-tag-slot)
2167 (mapcar (function (lambda (x) (if (consp x) x (list x))))
2168 descs)))
2169 (while opts
2170 (let ((opt (if (consp (car opts)) (caar opts) (car opts)))
69d8fb1e 2171 (args (cdr-safe (pop opts))))
64a4c526 2172 (cond ((eq opt :conc-name)
fcd73769
RS
2173 (if args
2174 (setq conc-name (if (car args)
2175 (symbol-name (car args)) ""))))
64a4c526 2176 ((eq opt :constructor)
fcd73769 2177 (if (cdr args)
40e8a6c3
SM
2178 (progn
2179 ;; If this defines a constructor of the same name as
2180 ;; the default one, don't define the default.
2181 (if (eq (car args) constructor)
2182 (setq constructor nil))
2183 (push args constrs))
fcd73769 2184 (if args (setq constructor (car args)))))
64a4c526 2185 ((eq opt :copier)
fcd73769 2186 (if args (setq copier (car args))))
64a4c526 2187 ((eq opt :predicate)
fcd73769 2188 (if args (setq predicate (car args))))
64a4c526 2189 ((eq opt :include)
fcd73769
RS
2190 (setq include (car args)
2191 include-descs (mapcar (function
2192 (lambda (x)
2193 (if (consp x) x (list x))))
36f0f2b1 2194 (cdr args))))
64a4c526 2195 ((eq opt :print-function)
fcd73769 2196 (setq print-func (car args)))
64a4c526 2197 ((eq opt :type)
fcd73769 2198 (setq type (car args)))
64a4c526 2199 ((eq opt :named)
fcd73769 2200 (setq named t))
64a4c526 2201 ((eq opt :initial-offset)
fcd73769
RS
2202 (setq descs (nconc (make-list (car args) '(cl-skip-slot))
2203 descs)))
2204 (t
2205 (error "Slot option %s unrecognized" opt)))))
2206 (if print-func
03fef3e6
SM
2207 (setq print-func
2208 `(progn (funcall #',print-func cl-x cl-s cl-n) t))
fcd73769
RS
2209 (or type (and include (not (get include 'cl-struct-print)))
2210 (setq print-auto t
2211 print-func (and (or (not (or include type)) (null print-func))
03fef3e6
SM
2212 `(progn
2213 (princ ,(format "#S(%s" name) cl-s))))))
fcd73769
RS
2214 (if include
2215 (let ((inc-type (get include 'cl-struct-type))
2216 (old-descs (get include 'cl-struct-slots)))
2217 (or inc-type (error "%s is not a struct name" include))
2218 (and type (not (eq (car inc-type) type))
2219 (error ":type disagrees with :include for %s" name))
2220 (while include-descs
2221 (setcar (memq (or (assq (caar include-descs) old-descs)
2222 (error "No slot %s in included struct %s"
2223 (caar include-descs) include))
2224 old-descs)
69d8fb1e 2225 (pop include-descs)))
fcd73769
RS
2226 (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs))
2227 type (car inc-type)
2228 named (assq 'cl-tag-slot descs))
2229 (if (cadr inc-type) (setq tag name named t))
36f0f2b1
RS
2230 (let ((incl include))
2231 (while incl
7c1898a7 2232 (push `(cl-pushnew ',tag
03fef3e6
SM
2233 ,(intern (format "cl-struct-%s-tags" incl)))
2234 forms)
36f0f2b1 2235 (setq incl (get incl 'cl-struct-include)))))
fcd73769
RS
2236 (if type
2237 (progn
2238 (or (memq type '(vector list))
4920bd1e 2239 (error "Invalid :type specifier: %s" type))
fcd73769
RS
2240 (if named (setq tag name)))
2241 (setq type 'vector named 'true)))
2242 (or named (setq descs (delq (assq 'cl-tag-slot descs) descs)))
03fef3e6 2243 (push `(defvar ,tag-symbol) forms)
fcd73769
RS
2244 (setq pred-form (and named
2245 (let ((pos (- (length descs)
2246 (length (memq (assq 'cl-tag-slot descs)
2247 descs)))))
2248 (if (eq type 'vector)
03fef3e6
SM
2249 `(and (vectorp cl-x)
2250 (>= (length cl-x) ,(length descs))
2251 (memq (aref cl-x ,pos) ,tag-symbol))
fcd73769 2252 (if (= pos 0)
03fef3e6
SM
2253 `(memq (car-safe cl-x) ,tag-symbol)
2254 `(and (consp cl-x)
2255 (memq (nth ,pos cl-x) ,tag-symbol))))))
fcd73769 2256 pred-check (and pred-form (> safety 0)
7c1898a7 2257 (if (and (eq (cl-caadr pred-form) 'vectorp)
fcd73769 2258 (= safety 1))
7c1898a7 2259 (cons 'and (cl-cdddr pred-form)) pred-form)))
fcd73769
RS
2260 (let ((pos 0) (descp descs))
2261 (while descp
69d8fb1e 2262 (let* ((desc (pop descp))
fcd73769
RS
2263 (slot (car desc)))
2264 (if (memq slot '(cl-tag-slot cl-skip-slot))
2265 (progn
69d8fb1e 2266 (push nil slots)
03fef3e6 2267 (push (and (eq slot 'cl-tag-slot) `',tag)
fcd73769
RS
2268 defaults))
2269 (if (assq slot descp)
2270 (error "Duplicate slots named %s in %s" slot name))
2271 (let ((accessor (intern (format "%s%s" conc-name slot))))
69d8fb1e
SM
2272 (push slot slots)
2273 (push (nth 1 desc) defaults)
2ee3d7f0
SM
2274 (push `(cl-defsubst ,accessor (cl-x)
2275 ,@(and pred-check
03fef3e6
SM
2276 (list `(or ,pred-check
2277 (error "%s accessing a non-%s"
2278 ',accessor ',name))))
2ee3d7f0
SM
2279 ,(if (eq type 'vector) `(aref cl-x ,pos)
2280 (if (= pos 0) '(car cl-x)
2281 `(nth ,pos cl-x)))) forms)
69d8fb1e 2282 (push (cons accessor t) side-eff)
2ee3d7f0
SM
2283 ;; Don't bother defining a setf-expander, since gv-get can use
2284 ;; the compiler macro to get the same result.
2285 ;;(push `(gv-define-setter ,accessor (cl-val cl-x)
2286 ;; ,(if (cadr (memq :read-only (cddr desc)))
2287 ;; `(progn (ignore cl-x cl-val)
2288 ;; (error "%s is a read-only slot"
2289 ;; ',accessor))
2290 ;; ;; If cl is loaded only for compilation,
2291 ;; ;; the call to cl--struct-setf-expander would
2292 ;; ;; cause a warning because it may not be
2293 ;; ;; defined at run time. Suppress that warning.
2294 ;; `(progn
2295 ;; (declare-function
2296 ;; cl--struct-setf-expander "cl-macs"
2297 ;; (x name accessor pred-form pos))
2298 ;; (cl--struct-setf-expander
2299 ;; cl-val cl-x ',name ',accessor
2300 ;; ,(and pred-check `',pred-check)
2301 ;; ,pos))))
2302 ;; forms)
fcd73769
RS
2303 (if print-auto
2304 (nconc print-func
03fef3e6
SM
2305 (list `(princ ,(format " %s" slot) cl-s)
2306 `(prin1 (,accessor cl-x) cl-s)))))))
fcd73769
RS
2307 (setq pos (1+ pos))))
2308 (setq slots (nreverse slots)
2309 defaults (nreverse defaults))
2310 (and predicate pred-form
7c1898a7 2311 (progn (push `(cl-defsubst ,predicate (cl-x)
03fef3e6
SM
2312 ,(if (eq (car pred-form) 'and)
2313 (append pred-form '(t))
2314 `(and ,pred-form t))) forms)
69d8fb1e 2315 (push (cons predicate 'error-free) side-eff)))
fcd73769 2316 (and copier
03fef3e6 2317 (progn (push `(defun ,copier (x) (copy-sequence x)) forms)
69d8fb1e 2318 (push (cons copier t) side-eff)))
fcd73769 2319 (if constructor
69d8fb1e 2320 (push (list constructor
fcd73769
RS
2321 (cons '&key (delq nil (copy-sequence slots))))
2322 constrs))
2323 (while constrs
2324 (let* ((name (caar constrs))
69d8fb1e 2325 (args (cadr (pop constrs)))
4dd1c416 2326 (anames (cl--arglist-args args))
7c1898a7 2327 (make (cl-mapcar (function (lambda (s d) (if (memq s anames) s d)))
fcd73769 2328 slots defaults)))
7c1898a7 2329 (push `(cl-defsubst ,name
03fef3e6
SM
2330 (&cl-defs '(nil ,@descs) ,@args)
2331 (,type ,@make)) forms)
4dd1c416 2332 (if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs)))
69d8fb1e 2333 (push (cons name t) side-eff))))
fcd73769 2334 (if print-auto (nconc print-func (list '(princ ")" cl-s) t)))
5a315f9c
SM
2335 ;; Don't bother adding to cl-custom-print-functions since it's not used
2336 ;; by anything anyway!
2337 ;;(if print-func
2338 ;; (push `(if (boundp 'cl-custom-print-functions)
2339 ;; (push
2340 ;; ;; The auto-generated function does not pay attention to
2341 ;; ;; the depth argument cl-n.
2342 ;; (lambda (cl-x cl-s ,(if print-auto '_cl-n 'cl-n))
2343 ;; (and ,pred-form ,print-func))
2344 ;; cl-custom-print-functions))
2345 ;; forms))
03fef3e6 2346 (push `(setq ,tag-symbol (list ',tag)) forms)
7c1898a7 2347 (push `(cl-eval-when (compile load eval)
03fef3e6
SM
2348 (put ',name 'cl-struct-slots ',descs)
2349 (put ',name 'cl-struct-type ',(list type (eq named t)))
2350 (put ',name 'cl-struct-include ',include)
2351 (put ',name 'cl-struct-print ,print-auto)
2352 ,@(mapcar (lambda (x)
2353 `(put ',(car x) 'side-effect-free ',(cdr x)))
2354 side-eff))
2355 forms)
2356 `(progn ,@(nreverse (cons `',name forms)))))
fcd73769 2357
fcd73769
RS
2358;;; Types and assertions.
2359
15120dec 2360;;;###autoload
7c1898a7 2361(defmacro cl-deftype (name arglist &rest body)
64a4c526 2362 "Define NAME as a new data type.
7c1898a7
SM
2363The type name can then be used in `cl-typecase', `cl-check-type', etc."
2364 (declare (debug cl-defmacro) (doc-string 3))
2365 `(cl-eval-when (compile load eval)
4302f5ba
SM
2366 (put ',name 'cl-deftype-handler
2367 (cl-function (lambda (&cl-defs '('*) ,@arglist) ,@body)))))
fcd73769 2368
4dd1c416 2369(defun cl--make-type-test (val type)
fcd73769
RS
2370 (if (symbolp type)
2371 (cond ((get type 'cl-deftype-handler)
4dd1c416 2372 (cl--make-type-test val (funcall (get type 'cl-deftype-handler))))
fcd73769 2373 ((memq type '(nil t)) type)
e0b16322 2374 ((eq type 'null) `(null ,val))
578f8106 2375 ((eq type 'atom) `(atom ,val))
7c1898a7 2376 ((eq type 'float) `(cl-floatp-safe ,val))
e0b16322
SM
2377 ((eq type 'real) `(numberp ,val))
2378 ((eq type 'fixnum) `(integerp ,val))
7c1898a7 2379 ;; FIXME: Should `character' accept things like ?\C-\M-a ? --Stef
31ff0ac1 2380 ((memq type '(character string-char)) `(characterp ,val))
fcd73769
RS
2381 (t
2382 (let* ((name (symbol-name type))
2383 (namep (intern (concat name "p"))))
2384 (if (fboundp namep) (list namep val)
2385 (list (intern (concat name "-p")) val)))))
2386 (cond ((get (car type) 'cl-deftype-handler)
4dd1c416 2387 (cl--make-type-test val (apply (get (car type) 'cl-deftype-handler)
fcd73769 2388 (cdr type))))
e0b16322 2389 ((memq (car type) '(integer float real number))
4dd1c416 2390 (delq t `(and ,(cl--make-type-test val (car type))
03fef3e6 2391 ,(if (memq (cadr type) '(* nil)) t
7c1898a7 2392 (if (consp (cadr type)) `(> ,val ,(cl-caadr type))
03fef3e6 2393 `(>= ,val ,(cadr type))))
7c1898a7
SM
2394 ,(if (memq (cl-caddr type) '(* nil)) t
2395 (if (consp (cl-caddr type)) `(< ,val ,(cl-caaddr type))
2396 `(<= ,val ,(cl-caddr type)))))))
e0b16322 2397 ((memq (car type) '(and or not))
fcd73769 2398 (cons (car type)
4dd1c416 2399 (mapcar (function (lambda (x) (cl--make-type-test val x)))
fcd73769 2400 (cdr type))))
7c1898a7
SM
2401 ((memq (car type) '(member cl-member))
2402 `(and (cl-member ,val ',(cdr type)) t))
e0b16322 2403 ((eq (car type) 'satisfies) (list (cadr type) val))
fcd73769
RS
2404 (t (error "Bad type spec: %s" type)))))
2405
513749ee 2406(defvar cl--object)
ebacfcc6 2407;;;###autoload
7c1898a7 2408(defun cl-typep (object type) ; See compiler macro below.
fcd73769
RS
2409 "Check that OBJECT is of type TYPE.
2410TYPE is a Common Lisp-style type specifier."
513749ee
SM
2411 (let ((cl--object object)) ;; Yuck!!
2412 (eval (cl--make-type-test 'cl--object type))))
fcd73769 2413
ebacfcc6 2414;;;###autoload
7c1898a7 2415(defmacro cl-check-type (form type &optional string)
fcd73769
RS
2416 "Verify that FORM is of type TYPE; signal an error if not.
2417STRING is an optional description of the desired type."
b1198e17 2418 (declare (debug (place cl-type-spec &optional stringp)))
bb3faf5b 2419 (and (or (not (cl--compiling-file))
fcd73769 2420 (< cl-optimize-speed 3) (= cl-optimize-safety 3))
4dd1c416 2421 (let* ((temp (if (cl--simple-expr-p form 3)
e542ea4b 2422 form (make-symbol "--cl-var--")))
4dd1c416 2423 (body `(or ,(cl--make-type-test temp type)
03fef3e6
SM
2424 (signal 'wrong-type-argument
2425 (list ,(or string `',type)
2426 ,temp ',form)))))
2427 (if (eq temp form) `(progn ,body nil)
2428 `(let ((,temp ,form)) ,body nil)))))
fcd73769 2429
ebacfcc6 2430;;;###autoload
7c1898a7 2431(defmacro cl-assert (form &optional show-args string &rest args)
fcd73769
RS
2432 "Verify that FORM returns non-nil; signal an error if not.
2433Second arg SHOW-ARGS means to include arguments of FORM in message.
2434Other args STRING and ARGS... are arguments to be passed to `error'.
2435They are not evaluated unless the assertion fails. If STRING is
2436omitted, a default message listing FORM itself is used."
b1198e17 2437 (declare (debug (form &rest form)))
bb3faf5b 2438 (and (or (not (cl--compiling-file))
fcd73769 2439 (< cl-optimize-speed 3) (= cl-optimize-safety 3))
2b88d62a 2440 (let ((sargs (and show-args
4dd1c416
SM
2441 (delq nil (mapcar (lambda (x)
2442 (unless (macroexp-const-p x)
2443 x))
2444 (cdr form))))))
03fef3e6
SM
2445 `(progn
2446 (or ,form
2447 ,(if string
2448 `(error ,string ,@sargs ,@args)
2449 `(signal 'cl-assertion-failed
2450 (list ',form ,@sargs))))
2451 nil))))
fcd73769 2452
fcd73769
RS
2453;;; Compiler macros.
2454
ebacfcc6 2455;;;###autoload
7c1898a7 2456(defmacro cl-define-compiler-macro (func args &rest body)
64a4c526 2457 "Define a compiler-only macro.
fcd73769
RS
2458This is like `defmacro', but macro expansion occurs only if the call to
2459FUNC is compiled (i.e., not interpreted). Compiler macros should be used
2460for optimizing the way calls to FUNC are compiled; the form returned by
2461BODY should do the same thing as a call to the normal function called
2462FUNC, though possibly more efficiently. Note that, like regular macros,
2463compiler macros are expanded repeatedly until no further expansions are
2464possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
2465original function call alone by declaring an initial `&whole foo' parameter
2466and then returning foo."
7c1898a7 2467 (declare (debug cl-defmacro))
16c9c10f 2468 (let ((p args) (res nil))
69d8fb1e 2469 (while (consp p) (push (pop p) res))
16c9c10f 2470 (setq args (nconc (nreverse res) (and p (list '&rest p)))))
7c1898a7 2471 `(cl-eval-when (compile load eval)
4302f5ba
SM
2472 (put ',func 'compiler-macro
2473 (cl-function (lambda ,(if (memq '&whole args) (delq '&whole args)
2474 (cons '_cl-whole-arg args))
2475 ,@body)))
57a7d507
SM
2476 ;; This is so that describe-function can locate
2477 ;; the macro definition.
2478 (let ((file ,(or buffer-file-name
2479 (and (boundp 'byte-compile-current-file)
2480 (stringp byte-compile-current-file)
2481 byte-compile-current-file))))
2482 (if file (put ',func 'compiler-macro-file
2483 (purecopy (file-name-nondirectory file)))))))
fcd73769 2484
ebacfcc6 2485;;;###autoload
7c1898a7 2486(defun cl-compiler-macroexpand (form)
fcd73769
RS
2487 (while
2488 (let ((func (car-safe form)) (handler nil))
2489 (while (and (symbolp func)
57a7d507 2490 (not (setq handler (get func 'compiler-macro)))
fcd73769
RS
2491 (fboundp func)
2492 (or (not (eq (car-safe (symbol-function func)) 'autoload))
2493 (load (nth 1 (symbol-function func)))))
2494 (setq func (symbol-function func)))
2495 (and handler
2496 (not (eq form (setq form (apply handler form (cdr form))))))))
2497 form)
2498
414dbb00
SM
2499;; Optimize away unused block-wrappers.
2500
4dd1c416 2501(defvar cl--active-block-names nil)
414dbb00 2502
bb3faf5b 2503(cl-define-compiler-macro cl--block-wrapper (cl-form)
414dbb00 2504 (let* ((cl-entry (cons (nth 1 (nth 1 cl-form)) nil))
4dd1c416 2505 (cl--active-block-names (cons cl-entry cl--active-block-names))
414dbb00
SM
2506 (cl-body (macroexpand-all ;Performs compiler-macro expansions.
2507 (cons 'progn (cddr cl-form))
2508 macroexpand-all-environment)))
2509 ;; FIXME: To avoid re-applying macroexpand-all, we'd like to be able
2510 ;; to indicate that this return value is already fully expanded.
2511 (if (cdr cl-entry)
a08a25d7 2512 `(catch ,(nth 1 cl-form) ,@(cdr cl-body))
414dbb00
SM
2513 cl-body)))
2514
bb3faf5b 2515(cl-define-compiler-macro cl--block-throw (cl-tag cl-value)
4dd1c416 2516 (let ((cl-found (assq (nth 1 cl-tag) cl--active-block-names)))
414dbb00
SM
2517 (if cl-found (setcdr cl-found t)))
2518 `(throw ,cl-tag ,cl-value))
2519
eb123b12 2520;;;###autoload
7c1898a7 2521(defmacro cl-defsubst (name args &rest body)
69d8fb1e 2522 "Define NAME as a function.
fcd73769
RS
2523Like `defun', except the function is automatically declared `inline',
2524ARGLIST allows full Common Lisp conventions, and BODY is implicitly
7c1898a7 2525surrounded by (cl-block NAME ...).
69d8fb1e
SM
2526
2527\(fn NAME ARGLIST [DOCSTRING] BODY...)"
2ee3d7f0 2528 (declare (debug cl-defun) (indent 2))
4dd1c416 2529 (let* ((argns (cl--arglist-args args)) (p argns)
fcd73769 2530 (pbody (cons 'progn body))
4dd1c416
SM
2531 (unsafe (not (cl--safe-expr-p pbody))))
2532 (while (and p (eq (cl--expr-contains args (car p)) 1)) (pop p))
03fef3e6
SM
2533 `(progn
2534 ,(if p nil ; give up if defaults refer to earlier args
7c1898a7 2535 `(cl-define-compiler-macro ,name
03fef3e6
SM
2536 ,(if (memq '&key args)
2537 `(&whole cl-whole &cl-quote ,@args)
2538 (cons '&cl-quote args))
bb3faf5b 2539 (cl--defsubst-expand
7c1898a7 2540 ',argns '(cl-block ,name ,@body)
03fef3e6
SM
2541 ;; We used to pass `simple' as
2542 ;; (not (or unsafe (cl-expr-access-order pbody argns)))
2543 ;; But this is much too simplistic since it
2544 ;; does not pay attention to the argvs (and
2545 ;; cl-expr-access-order itself is also too naive).
2546 nil
2547 ,(and (memq '&key args) 'cl-whole) ,unsafe ,@argns)))
7c1898a7 2548 (cl-defun ,name ,args ,@body))))
fcd73769 2549
bb3faf5b 2550(defun cl--defsubst-expand (argns body simple whole unsafe &rest argvs)
4dd1c416
SM
2551 (if (and whole (not (cl--safe-expr-p (cons 'progn argvs)))) whole
2552 (if (cl--simple-exprs-p argvs) (setq simple t))
e754e83b
SM
2553 (let* ((substs ())
2554 (lets (delq nil
7c1898a7 2555 (cl-mapcar (lambda (argn argv)
4dd1c416 2556 (if (or simple (macroexp-const-p argv))
7c1898a7
SM
2557 (progn (push (cons argn argv) substs)
2558 (and unsafe (list argn argv)))
2559 (list argn argv)))
2560 argns argvs))))
e754e83b
SM
2561 ;; FIXME: `sublis/subst' will happily substitute the symbol
2562 ;; `argn' in places where it's not used as a reference
2563 ;; to a variable.
2564 ;; FIXME: `sublis/subst' will happily copy `argv' to a different
2565 ;; scope, leading to name capture.
2566 (setq body (cond ((null substs) body)
2567 ((null (cdr substs))
7c1898a7
SM
2568 (cl-subst (cdar substs) (caar substs) body))
2569 (t (cl-sublis substs body))))
03fef3e6 2570 (if lets `(let ,lets ,body) body))))
fcd73769
RS
2571
2572
9b77469a
SM
2573;; Compile-time optimizations for some functions defined in this package.
2574;; Note that cl.el arranges to force cl-macs to be loaded at compile-time,
2575;; mainly to make sure these macros will be present.
fcd73769 2576
d9857e53 2577(defun cl--compiler-macro-member (form a list &rest keys)
64a4c526 2578 (let ((test (and (= (length keys) 2) (eq (car keys) :test)
4dd1c416 2579 (cl--const-expr-val (nth 1 keys)))))
03fef3e6
SM
2580 (cond ((eq test 'eq) `(memq ,a ,list))
2581 ((eq test 'equal) `(member ,a ,list))
2582 ((or (null keys) (eq test 'eql)) `(memql ,a ,list))
fcd73769
RS
2583 (t form))))
2584
d9857e53 2585(defun cl--compiler-macro-assoc (form a list &rest keys)
64a4c526 2586 (let ((test (and (= (length keys) 2) (eq (car keys) :test)
4dd1c416 2587 (cl--const-expr-val (nth 1 keys)))))
03fef3e6
SM
2588 (cond ((eq test 'eq) `(assq ,a ,list))
2589 ((eq test 'equal) `(assoc ,a ,list))
4dd1c416
SM
2590 ((and (macroexp-const-p a) (or (null keys) (eq test 'eql)))
2591 (if (cl-floatp-safe (cl--const-expr-val a))
03fef3e6 2592 `(assoc ,a ,list) `(assq ,a ,list)))
fcd73769
RS
2593 (t form))))
2594
71adb94b 2595;;;###autoload
d9857e53 2596(defun cl--compiler-macro-adjoin (form a list &rest keys)
4dd1c416 2597 (if (and (cl--simple-expr-p a) (cl--simple-expr-p list)
64a4c526 2598 (not (memq :key keys)))
7c1898a7 2599 `(if (cl-member ,a ,list ,@keys) ,list (cons ,a ,list))
fcd73769
RS
2600 form))
2601
71adb94b 2602;;;###autoload
d9857e53 2603(defun cl--compiler-macro-list* (_form arg &rest others)
fcd73769
RS
2604 (let* ((args (reverse (cons arg others)))
2605 (form (car args)))
2606 (while (setq args (cdr args))
03fef3e6 2607 (setq form `(cons ,(car args) ,form)))
fcd73769
RS
2608 form))
2609
d9857e53 2610(defun cl--compiler-macro-get (_form sym prop &optional def)
fcd73769 2611 (if def
7c1898a7 2612 `(cl-getf (symbol-plist ,sym) ,prop ,def)
03fef3e6 2613 `(get ,sym ,prop)))
fcd73769 2614
7c1898a7 2615(cl-define-compiler-macro cl-typep (&whole form val type)
4dd1c416 2616 (if (macroexp-const-p type)
2ee3d7f0 2617 (macroexp-let2 macroexp-copyable-p temp val
d9857e53 2618 (cl--make-type-test temp (cl--const-expr-val type)))
fcd73769
RS
2619 form))
2620
71adb94b
SM
2621;;;###autoload
2622(defun cl--compiler-macro-cXXr (form x)
2623 (let* ((head (car form))
2624 (n (symbol-name (car form)))
2625 (i (- (length n) 2)))
2626 (if (not (string-match "c[ad]+r\\'" n))
2627 (if (and (fboundp head) (symbolp (symbol-function head)))
2628 (cl--compiler-macro-cXXr (cons (symbol-function head) (cdr form))
2629 x)
2630 (error "Compiler macro for cXXr applied to non-cXXr form"))
2631 (while (> i (match-beginning 0))
2632 (setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
2633 (setq i (1- i)))
2634 x)))
2635
2636(dolist (y '(cl-first cl-second cl-third cl-fourth
2637 cl-fifth cl-sixth cl-seventh
2638 cl-eighth cl-ninth cl-tenth
2639 cl-rest cl-endp cl-plusp cl-minusp
2640 cl-caaar cl-caadr cl-cadar
2641 cl-caddr cl-cdaar cl-cdadr
2642 cl-cddar cl-cdddr cl-caaaar
2643 cl-caaadr cl-caadar cl-caaddr
2644 cl-cadaar cl-cadadr cl-caddar
2645 cl-cadddr cl-cdaaar cl-cdaadr
2646 cl-cdadar cl-cdaddr cl-cddaar
2647 cl-cddadr cl-cdddar cl-cddddr))
2648 (put y 'side-effect-free t))
fcd73769
RS
2649
2650;;; Things that are inline.
2ee3d7f0
SM
2651(cl-proclaim '(inline cl-floatp-safe cl-acons cl-map cl-concatenate cl-notany
2652 cl-notevery cl--set-elt cl-revappend cl-nreconc gethash))
fcd73769
RS
2653
2654;;; Things that are side-effect-free.
e542ea4b 2655(mapc (lambda (x) (put x 'side-effect-free t))
7c1898a7
SM
2656 '(cl-oddp cl-evenp cl-signum last butlast cl-ldiff cl-pairlis cl-gcd cl-lcm
2657 cl-isqrt cl-floor cl-ceiling cl-truncate cl-round cl-mod cl-rem cl-subseq
2658 cl-list-length cl-get cl-getf))
fcd73769
RS
2659
2660;;; Things that are side-effect-and-error-free.
e542ea4b 2661(mapc (lambda (x) (put x 'side-effect-free 'error-free))
7c1898a7
SM
2662 '(eql cl-floatp-safe cl-list* cl-subst cl-acons cl-equalp cl-random-state-p
2663 copy-tree cl-sublis))
fcd73769
RS
2664
2665
2666(run-hooks 'cl-macs-load-hook)
2667
ebacfcc6 2668;; Local variables:
bc8ce89b
GM
2669;; byte-compile-dynamic: t
2670;; byte-compile-warnings: (not cl-functions)
ebacfcc6
SM
2671;; generated-autoload-file: "cl-loaddefs.el"
2672;; End:
b69a3374 2673
de7e2b36
SM
2674(provide 'cl-macs)
2675
fcd73769 2676;;; cl-macs.el ends here