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