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