* lisp/emacs-lisp/cl-macs.el (cl--sm-macroexpand): Fix handling of
[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...)"
b1198e17 734 (declare (debug (&rest &or symbolp form)))
513749ee
SM
735 (if (not (memq t (mapcar 'symbolp (delq nil (delq t (cl-copy-list loop-args))))))
736 `(cl-block nil (while t ,@loop-args))
737 (let ((cl--loop-args loop-args) (cl--loop-name nil) (cl--loop-bindings nil)
4dd1c416
SM
738 (cl--loop-body nil) (cl--loop-steps nil)
739 (cl--loop-result nil) (cl--loop-result-explicit nil)
740 (cl--loop-result-var nil) (cl--loop-finish-flag nil)
741 (cl--loop-accum-var nil) (cl--loop-accum-vars nil)
742 (cl--loop-initially nil) (cl--loop-finally nil)
743 (cl--loop-map-form nil) (cl--loop-first-flag nil)
744 (cl--loop-destr-temps nil) (cl--loop-symbol-macs nil))
745 (setq cl--loop-args (append cl--loop-args '(cl-end-loop)))
746 (while (not (eq (car cl--loop-args) 'cl-end-loop)) (cl-parse-loop-clause))
747 (if cl--loop-finish-flag
748 (push `((,cl--loop-finish-flag t)) cl--loop-bindings))
749 (if cl--loop-first-flag
750 (progn (push `((,cl--loop-first-flag t)) cl--loop-bindings)
751 (push `(setq ,cl--loop-first-flag nil) cl--loop-steps)))
752 (let* ((epilogue (nconc (nreverse cl--loop-finally)
753 (list (or cl--loop-result-explicit cl--loop-result))))
754 (ands (cl--loop-build-ands (nreverse cl--loop-body)))
755 (while-body (nconc (cadr ands) (nreverse cl--loop-steps)))
fcd73769 756 (body (append
4dd1c416
SM
757 (nreverse cl--loop-initially)
758 (list (if cl--loop-map-form
7c1898a7
SM
759 `(cl-block --cl-finish--
760 ,(cl-subst
03fef3e6
SM
761 (if (eq (car ands) t) while-body
762 (cons `(or ,(car ands)
7c1898a7 763 (cl-return-from --cl-finish--
03fef3e6
SM
764 nil))
765 while-body))
4dd1c416 766 '--cl-map cl--loop-map-form))
03fef3e6 767 `(while ,(car ands) ,@while-body)))
4dd1c416
SM
768 (if cl--loop-finish-flag
769 (if (equal epilogue '(nil)) (list cl--loop-result-var)
770 `((if ,cl--loop-finish-flag
771 (progn ,@epilogue) ,cl--loop-result-var)))
fcd73769 772 epilogue))))
4dd1c416
SM
773 (if cl--loop-result-var (push (list cl--loop-result-var) cl--loop-bindings))
774 (while cl--loop-bindings
775 (if (cdar cl--loop-bindings)
776 (setq body (list (cl--loop-let (pop cl--loop-bindings) body t)))
fcd73769 777 (let ((lets nil))
4dd1c416
SM
778 (while (and cl--loop-bindings
779 (not (cdar cl--loop-bindings)))
780 (push (car (pop cl--loop-bindings)) lets))
781 (setq body (list (cl--loop-let lets body nil))))))
782 (if cl--loop-symbol-macs
783 (setq body (list `(cl-symbol-macrolet ,cl--loop-symbol-macs ,@body))))
784 `(cl-block ,cl--loop-name ,@body)))))
fcd73769 785
7c1898a7 786;; Below is a complete spec for cl-loop, in several parts that correspond
b1198e17
SM
787;; to the syntax given in CLtL2. The specs do more than specify where
788;; the forms are; it also specifies, as much as Edebug allows, all the
7c1898a7 789;; syntactically valid cl-loop clauses. The disadvantage of this
b1198e17
SM
790;; completeness is rigidity, but the "for ... being" clause allows
791;; arbitrary extensions of the form: [symbolp &rest &or symbolp form].
792
7c1898a7 793;; (def-edebug-spec cl-loop
b1198e17
SM
794;; ([&optional ["named" symbolp]]
795;; [&rest
796;; &or
797;; ["repeat" form]
798;; loop-for-as
799;; loop-with
800;; loop-initial-final]
801;; [&rest loop-clause]
802;; ))
803
804;; (def-edebug-spec loop-with
805;; ("with" loop-var
806;; loop-type-spec
807;; [&optional ["=" form]]
808;; &rest ["and" loop-var
809;; loop-type-spec
810;; [&optional ["=" form]]]))
811
812;; (def-edebug-spec loop-for-as
813;; ([&or "for" "as"] loop-for-as-subclause
814;; &rest ["and" loop-for-as-subclause]))
815
816;; (def-edebug-spec loop-for-as-subclause
817;; (loop-var
818;; loop-type-spec
819;; &or
820;; [[&or "in" "on" "in-ref" "across-ref"]
821;; form &optional ["by" function-form]]
822
823;; ["=" form &optional ["then" form]]
824;; ["across" form]
825;; ["being"
826;; [&or "the" "each"]
827;; &or
828;; [[&or "element" "elements"]
829;; [&or "of" "in" "of-ref"] form
830;; &optional "using" ["index" symbolp]];; is this right?
831;; [[&or "hash-key" "hash-keys"
832;; "hash-value" "hash-values"]
833;; [&or "of" "in"]
834;; hash-table-p &optional ["using" ([&or "hash-value" "hash-values"
835;; "hash-key" "hash-keys"] sexp)]]
836
837;; [[&or "symbol" "present-symbol" "external-symbol"
838;; "symbols" "present-symbols" "external-symbols"]
839;; [&or "in" "of"] package-p]
840
841;; ;; Extensions for Emacs Lisp, including Lucid Emacs.
842;; [[&or "frame" "frames"
843;; "screen" "screens"
844;; "buffer" "buffers"]]
845
846;; [[&or "window" "windows"]
847;; [&or "of" "in"] form]
848
849;; [[&or "overlay" "overlays"
850;; "extent" "extents"]
851;; [&or "of" "in"] form
852;; &optional [[&or "from" "to"] form]]
853
854;; [[&or "interval" "intervals"]
855;; [&or "in" "of"] form
856;; &optional [[&or "from" "to"] form]
857;; ["property" form]]
858
859;; [[&or "key-code" "key-codes"
860;; "key-seq" "key-seqs"
861;; "key-binding" "key-bindings"]
862;; [&or "in" "of"] form
863;; &optional ["using" ([&or "key-code" "key-codes"
864;; "key-seq" "key-seqs"
865;; "key-binding" "key-bindings"]
866;; sexp)]]
867;; ;; For arbitrary extensions, recognize anything else.
868;; [symbolp &rest &or symbolp form]
869;; ]
870
871;; ;; arithmetic - must be last since all parts are optional.
872;; [[&optional [[&or "from" "downfrom" "upfrom"] form]]
873;; [&optional [[&or "to" "downto" "upto" "below" "above"] form]]
874;; [&optional ["by" form]]
875;; ]))
876
877;; (def-edebug-spec loop-initial-final
878;; (&or ["initially"
879;; ;; [&optional &or "do" "doing"] ;; CLtL2 doesn't allow this.
880;; &rest loop-non-atomic-expr]
881;; ["finally" &or
882;; [[&optional &or "do" "doing"] &rest loop-non-atomic-expr]
883;; ["return" form]]))
884
885;; (def-edebug-spec loop-and-clause
886;; (loop-clause &rest ["and" loop-clause]))
887
888;; (def-edebug-spec loop-clause
889;; (&or
890;; [[&or "while" "until" "always" "never" "thereis"] form]
891
892;; [[&or "collect" "collecting"
893;; "append" "appending"
894;; "nconc" "nconcing"
895;; "concat" "vconcat"] form
896;; [&optional ["into" loop-var]]]
897
898;; [[&or "count" "counting"
899;; "sum" "summing"
900;; "maximize" "maximizing"
901;; "minimize" "minimizing"] form
902;; [&optional ["into" loop-var]]
903;; loop-type-spec]
904
905;; [[&or "if" "when" "unless"]
906;; form loop-and-clause
907;; [&optional ["else" loop-and-clause]]
908;; [&optional "end"]]
909
910;; [[&or "do" "doing"] &rest loop-non-atomic-expr]
911
912;; ["return" form]
913;; loop-initial-final
914;; ))
915
916;; (def-edebug-spec loop-non-atomic-expr
917;; ([&not atom] form))
918
919;; (def-edebug-spec loop-var
920;; ;; The symbolp must be last alternative to recognize e.g. (a b . c)
921;; ;; loop-var =>
922;; ;; (loop-var . [&or nil loop-var])
923;; ;; (symbolp . [&or nil loop-var])
924;; ;; (symbolp . loop-var)
925;; ;; (symbolp . (symbolp . [&or nil loop-var]))
926;; ;; (symbolp . (symbolp . loop-var))
927;; ;; (symbolp . (symbolp . symbolp)) == (symbolp symbolp . symbolp)
928;; (&or (loop-var . [&or nil loop-var]) [gate symbolp]))
929
930;; (def-edebug-spec loop-type-spec
931;; (&optional ["of-type" loop-d-type-spec]))
932
933;; (def-edebug-spec loop-d-type-spec
934;; (&or (loop-d-type-spec . [&or nil loop-d-type-spec]) cl-type-spec))
935
936
937
215461a8 938(defun cl-parse-loop-clause () ; uses loop-*
4dd1c416 939 (let ((word (pop cl--loop-args))
fcd73769
RS
940 (hash-types '(hash-key hash-keys hash-value hash-values))
941 (key-types '(key-code key-codes key-seq key-seqs
942 key-binding key-bindings)))
943 (cond
944
4dd1c416 945 ((null cl--loop-args)
7c1898a7 946 (error "Malformed `cl-loop' macro"))
fcd73769
RS
947
948 ((eq word 'named)
4dd1c416 949 (setq cl--loop-name (pop cl--loop-args)))
fcd73769
RS
950
951 ((eq word 'initially)
4dd1c416
SM
952 (if (memq (car cl--loop-args) '(do doing)) (pop cl--loop-args))
953 (or (consp (car cl--loop-args)) (error "Syntax error on `initially' clause"))
954 (while (consp (car cl--loop-args))
955 (push (pop cl--loop-args) cl--loop-initially)))
fcd73769
RS
956
957 ((eq word 'finally)
4dd1c416
SM
958 (if (eq (car cl--loop-args) 'return)
959 (setq cl--loop-result-explicit (or (cl-pop2 cl--loop-args) '(quote nil)))
960 (if (memq (car cl--loop-args) '(do doing)) (pop cl--loop-args))
961 (or (consp (car cl--loop-args)) (error "Syntax error on `finally' clause"))
962 (if (and (eq (caar cl--loop-args) 'return) (null cl--loop-name))
963 (setq cl--loop-result-explicit (or (nth 1 (pop cl--loop-args)) '(quote nil)))
964 (while (consp (car cl--loop-args))
965 (push (pop cl--loop-args) cl--loop-finally)))))
fcd73769
RS
966
967 ((memq word '(for as))
968 (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil)
969 (ands nil))
970 (while
7c1898a7 971 ;; Use `cl-gensym' rather than `make-symbol'. It's important that
443b961a 972 ;; (not (eq (symbol-name var1) (symbol-name var2))) because
4dd1c416
SM
973 ;; these vars get added to the macro-environment.
974 (let ((var (or (pop cl--loop-args) (cl-gensym "--cl-var--"))))
975 (setq word (pop cl--loop-args))
976 (if (eq word 'being) (setq word (pop cl--loop-args)))
977 (if (memq word '(the each)) (setq word (pop cl--loop-args)))
fcd73769 978 (if (memq word '(buffer buffers))
4dd1c416 979 (setq word 'in cl--loop-args (cons '(buffer-list) cl--loop-args)))
fcd73769
RS
980 (cond
981
982 ((memq word '(from downfrom upfrom to downto upto
983 above below by))
4dd1c416
SM
984 (push word cl--loop-args)
985 (if (memq (car cl--loop-args) '(downto above))
7c1898a7 986 (error "Must specify `from' value for downward cl-loop"))
4dd1c416
SM
987 (let* ((down (or (eq (car cl--loop-args) 'downfrom)
988 (memq (cl-caddr cl--loop-args) '(downto above))))
989 (excl (or (memq (car cl--loop-args) '(above below))
990 (memq (cl-caddr cl--loop-args) '(above below))))
991 (start (and (memq (car cl--loop-args) '(from upfrom downfrom))
992 (cl-pop2 cl--loop-args)))
993 (end (and (memq (car cl--loop-args)
fcd73769 994 '(to upto downto above below))
4dd1c416
SM
995 (cl-pop2 cl--loop-args)))
996 (step (and (eq (car cl--loop-args) 'by) (cl-pop2 cl--loop-args)))
997 (end-var (and (not (macroexp-const-p end))
e542ea4b 998 (make-symbol "--cl-var--")))
4dd1c416 999 (step-var (and (not (macroexp-const-p step))
e542ea4b 1000 (make-symbol "--cl-var--"))))
fcd73769
RS
1001 (and step (numberp step) (<= step 0)
1002 (error "Loop `by' value is not positive: %s" step))
69d8fb1e
SM
1003 (push (list var (or start 0)) loop-for-bindings)
1004 (if end-var (push (list end-var end) loop-for-bindings))
1005 (if step-var (push (list step-var step)
e542ea4b 1006 loop-for-bindings))
fcd73769 1007 (if end
69d8fb1e 1008 (push (list
e542ea4b 1009 (if down (if excl '> '>=) (if excl '< '<=))
4dd1c416 1010 var (or end-var end)) cl--loop-body))
69d8fb1e 1011 (push (list var (list (if down '- '+) var
e542ea4b
SM
1012 (or step-var step 1)))
1013 loop-for-steps)))
fcd73769
RS
1014
1015 ((memq word '(in in-ref on))
1016 (let* ((on (eq word 'on))
e542ea4b
SM
1017 (temp (if (and on (symbolp var))
1018 var (make-symbol "--cl-var--"))))
4dd1c416
SM
1019 (push (list temp (pop cl--loop-args)) loop-for-bindings)
1020 (push `(consp ,temp) cl--loop-body)
fcd73769 1021 (if (eq word 'in-ref)
4dd1c416 1022 (push (list var `(car ,temp)) cl--loop-symbol-macs)
fcd73769
RS
1023 (or (eq temp var)
1024 (progn
69d8fb1e 1025 (push (list var nil) loop-for-bindings)
03fef3e6 1026 (push (list var (if on temp `(car ,temp)))
e542ea4b 1027 loop-for-sets))))
69d8fb1e 1028 (push (list temp
4dd1c416
SM
1029 (if (eq (car cl--loop-args) 'by)
1030 (let ((step (cl-pop2 cl--loop-args)))
e542ea4b
SM
1031 (if (and (memq (car-safe step)
1032 '(quote function
7c1898a7 1033 cl-function))
e542ea4b
SM
1034 (symbolp (nth 1 step)))
1035 (list (nth 1 step) temp)
03fef3e6
SM
1036 `(funcall ,step ,temp)))
1037 `(cdr ,temp)))
e542ea4b 1038 loop-for-steps)))
fcd73769
RS
1039
1040 ((eq word '=)
4dd1c416
SM
1041 (let* ((start (pop cl--loop-args))
1042 (then (if (eq (car cl--loop-args) 'then) (cl-pop2 cl--loop-args) start)))
69d8fb1e 1043 (push (list var nil) loop-for-bindings)
4dd1c416 1044 (if (or ands (eq (car cl--loop-args) 'and))
fcd73769 1045 (progn
e542ea4b 1046 (push `(,var
4dd1c416
SM
1047 (if ,(or cl--loop-first-flag
1048 (setq cl--loop-first-flag
e542ea4b
SM
1049 (make-symbol "--cl-var--")))
1050 ,start ,var))
1051 loop-for-sets)
69d8fb1e
SM
1052 (push (list var then) loop-for-steps))
1053 (push (list var
e542ea4b 1054 (if (eq start then) start
4dd1c416
SM
1055 `(if ,(or cl--loop-first-flag
1056 (setq cl--loop-first-flag
e542ea4b
SM
1057 (make-symbol "--cl-var--")))
1058 ,start ,then)))
1059 loop-for-sets))))
fcd73769
RS
1060
1061 ((memq word '(across across-ref))
e542ea4b
SM
1062 (let ((temp-vec (make-symbol "--cl-vec--"))
1063 (temp-idx (make-symbol "--cl-idx--")))
4dd1c416 1064 (push (list temp-vec (pop cl--loop-args)) loop-for-bindings)
69d8fb1e 1065 (push (list temp-idx -1) loop-for-bindings)
03fef3e6 1066 (push `(< (setq ,temp-idx (1+ ,temp-idx))
4dd1c416 1067 (length ,temp-vec)) cl--loop-body)
fcd73769 1068 (if (eq word 'across-ref)
03fef3e6 1069 (push (list var `(aref ,temp-vec ,temp-idx))
4dd1c416 1070 cl--loop-symbol-macs)
69d8fb1e 1071 (push (list var nil) loop-for-bindings)
03fef3e6 1072 (push (list var `(aref ,temp-vec ,temp-idx))
e542ea4b 1073 loop-for-sets))))
fcd73769
RS
1074
1075 ((memq word '(element elements))
4dd1c416
SM
1076 (let ((ref (or (memq (car cl--loop-args) '(in-ref of-ref))
1077 (and (not (memq (car cl--loop-args) '(in of)))
fcd73769 1078 (error "Expected `of'"))))
4dd1c416 1079 (seq (cl-pop2 cl--loop-args))
e542ea4b 1080 (temp-seq (make-symbol "--cl-seq--"))
4dd1c416
SM
1081 (temp-idx (if (eq (car cl--loop-args) 'using)
1082 (if (and (= (length (cadr cl--loop-args)) 2)
1083 (eq (cl-caadr cl--loop-args) 'index))
1084 (cadr (cl-pop2 cl--loop-args))
fcd73769 1085 (error "Bad `using' clause"))
e542ea4b 1086 (make-symbol "--cl-idx--"))))
69d8fb1e
SM
1087 (push (list temp-seq seq) loop-for-bindings)
1088 (push (list temp-idx 0) loop-for-bindings)
fcd73769 1089 (if ref
e542ea4b 1090 (let ((temp-len (make-symbol "--cl-len--")))
03fef3e6 1091 (push (list temp-len `(length ,temp-seq))
e542ea4b 1092 loop-for-bindings)
2eb87922 1093 (push (list var `(elt ,temp-seq ,temp-idx))
4dd1c416
SM
1094 cl--loop-symbol-macs)
1095 (push `(< ,temp-idx ,temp-len) cl--loop-body))
69d8fb1e 1096 (push (list var nil) loop-for-bindings)
03fef3e6
SM
1097 (push `(and ,temp-seq
1098 (or (consp ,temp-seq)
1099 (< ,temp-idx (length ,temp-seq))))
4dd1c416 1100 cl--loop-body)
03fef3e6
SM
1101 (push (list var `(if (consp ,temp-seq)
1102 (pop ,temp-seq)
1103 (aref ,temp-seq ,temp-idx)))
e542ea4b 1104 loop-for-sets))
03fef3e6 1105 (push (list temp-idx `(1+ ,temp-idx))
e542ea4b 1106 loop-for-steps)))
fcd73769
RS
1107
1108 ((memq word hash-types)
4dd1c416
SM
1109 (or (memq (car cl--loop-args) '(in of)) (error "Expected `of'"))
1110 (let* ((table (cl-pop2 cl--loop-args))
1111 (other (if (eq (car cl--loop-args) 'using)
1112 (if (and (= (length (cadr cl--loop-args)) 2)
1113 (memq (cl-caadr cl--loop-args) hash-types)
1114 (not (eq (cl-caadr cl--loop-args) word)))
1115 (cadr (cl-pop2 cl--loop-args))
fcd73769 1116 (error "Bad `using' clause"))
e542ea4b 1117 (make-symbol "--cl-var--"))))
fcd73769
RS
1118 (if (memq word '(hash-value hash-values))
1119 (setq var (prog1 other (setq other var))))
4dd1c416 1120 (setq cl--loop-map-form
e542ea4b 1121 `(maphash (lambda (,var ,other) . --cl-map) ,table))))
fcd73769
RS
1122
1123 ((memq word '(symbol present-symbol external-symbol
1124 symbols present-symbols external-symbols))
4dd1c416
SM
1125 (let ((ob (and (memq (car cl--loop-args) '(in of)) (cl-pop2 cl--loop-args))))
1126 (setq cl--loop-map-form
e542ea4b 1127 `(mapatoms (lambda (,var) . --cl-map) ,ob))))
fcd73769
RS
1128
1129 ((memq word '(overlay overlays extent extents))
1130 (let ((buf nil) (from nil) (to nil))
4dd1c416
SM
1131 (while (memq (car cl--loop-args) '(in of from to))
1132 (cond ((eq (car cl--loop-args) 'from) (setq from (cl-pop2 cl--loop-args)))
1133 ((eq (car cl--loop-args) 'to) (setq to (cl-pop2 cl--loop-args)))
1134 (t (setq buf (cl-pop2 cl--loop-args)))))
1135 (setq cl--loop-map-form
bb3faf5b 1136 `(cl--map-overlays
e542ea4b
SM
1137 (lambda (,var ,(make-symbol "--cl-var--"))
1138 (progn . --cl-map) nil)
1139 ,buf ,from ,to))))
fcd73769
RS
1140
1141 ((memq word '(interval intervals))
1142 (let ((buf nil) (prop nil) (from nil) (to nil)
e542ea4b
SM
1143 (var1 (make-symbol "--cl-var1--"))
1144 (var2 (make-symbol "--cl-var2--")))
4dd1c416
SM
1145 (while (memq (car cl--loop-args) '(in of property 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 ((eq (car cl--loop-args) 'property)
1149 (setq prop (cl-pop2 cl--loop-args)))
1150 (t (setq buf (cl-pop2 cl--loop-args)))))
fcd73769
RS
1151 (if (and (consp var) (symbolp (car var)) (symbolp (cdr var)))
1152 (setq var1 (car var) var2 (cdr var))
03fef3e6 1153 (push (list var `(cons ,var1 ,var2)) loop-for-sets))
4dd1c416 1154 (setq cl--loop-map-form
bb3faf5b 1155 `(cl--map-intervals
e542ea4b
SM
1156 (lambda (,var1 ,var2) . --cl-map)
1157 ,buf ,prop ,from ,to))))
fcd73769
RS
1158
1159 ((memq word key-types)
4dd1c416
SM
1160 (or (memq (car cl--loop-args) '(in of)) (error "Expected `of'"))
1161 (let ((cl-map (cl-pop2 cl--loop-args))
1162 (other (if (eq (car cl--loop-args) 'using)
1163 (if (and (= (length (cadr cl--loop-args)) 2)
1164 (memq (cl-caadr cl--loop-args) key-types)
1165 (not (eq (cl-caadr cl--loop-args) word)))
1166 (cadr (cl-pop2 cl--loop-args))
fcd73769 1167 (error "Bad `using' clause"))
e542ea4b 1168 (make-symbol "--cl-var--"))))
fcd73769
RS
1169 (if (memq word '(key-binding key-bindings))
1170 (setq var (prog1 other (setq other var))))
4dd1c416 1171 (setq cl--loop-map-form
e542ea4b 1172 `(,(if (memq word '(key-seq key-seqs))
bb3faf5b 1173 'cl--map-keymap-recursively 'map-keymap)
7c1898a7 1174 (lambda (,var ,other) . --cl-map) ,cl-map))))
fcd73769
RS
1175
1176 ((memq word '(frame frames screen screens))
e542ea4b 1177 (let ((temp (make-symbol "--cl-var--")))
69d8fb1e 1178 (push (list var '(selected-frame))
e542ea4b 1179 loop-for-bindings)
69d8fb1e 1180 (push (list temp nil) loop-for-bindings)
03fef3e6
SM
1181 (push `(prog1 (not (eq ,var ,temp))
1182 (or ,temp (setq ,temp ,var)))
4dd1c416 1183 cl--loop-body)
03fef3e6 1184 (push (list var `(next-frame ,var))
e542ea4b 1185 loop-for-steps)))
fcd73769
RS
1186
1187 ((memq word '(window windows))
4dd1c416 1188 (let ((scr (and (memq (car cl--loop-args) '(in of)) (cl-pop2 cl--loop-args)))
05907bb3
GM
1189 (temp (make-symbol "--cl-var--"))
1190 (minip (make-symbol "--cl-minip--")))
69d8fb1e 1191 (push (list var (if scr
03fef3e6 1192 `(frame-selected-window ,scr)
e542ea4b
SM
1193 '(selected-window)))
1194 loop-for-bindings)
05907bb3
GM
1195 ;; If we started in the minibuffer, we need to
1196 ;; ensure that next-window will bring us back there
1197 ;; at some point. (Bug#7492).
7c1898a7 1198 ;; (Consider using walk-windows instead of cl-loop if
05907bb3
GM
1199 ;; you care about such things.)
1200 (push (list minip `(minibufferp (window-buffer ,var)))
1201 loop-for-bindings)
69d8fb1e 1202 (push (list temp nil) loop-for-bindings)
03fef3e6
SM
1203 (push `(prog1 (not (eq ,var ,temp))
1204 (or ,temp (setq ,temp ,var)))
4dd1c416 1205 cl--loop-body)
03fef3e6 1206 (push (list var `(next-window ,var ,minip))
05907bb3 1207 loop-for-steps)))
fcd73769
RS
1208
1209 (t
1210 (let ((handler (and (symbolp word)
4dd1c416 1211 (get word 'cl--loop-for-handler))))
fcd73769
RS
1212 (if handler
1213 (funcall handler var)
1214 (error "Expected a `for' preposition, found %s" word)))))
4dd1c416 1215 (eq (car cl--loop-args) 'and))
fcd73769 1216 (setq ands t)
4dd1c416 1217 (pop cl--loop-args))
fcd73769 1218 (if (and ands loop-for-bindings)
4dd1c416
SM
1219 (push (nreverse loop-for-bindings) cl--loop-bindings)
1220 (setq cl--loop-bindings (nconc (mapcar 'list loop-for-bindings)
1221 cl--loop-bindings)))
fcd73769 1222 (if loop-for-sets
03fef3e6 1223 (push `(progn
4dd1c416
SM
1224 ,(cl--loop-let (nreverse loop-for-sets) 'setq ands)
1225 t) cl--loop-body))
fcd73769 1226 (if loop-for-steps
7c1898a7 1227 (push (cons (if ands 'cl-psetq 'setq)
e542ea4b 1228 (apply 'append (nreverse loop-for-steps)))
4dd1c416 1229 cl--loop-steps))))
fcd73769
RS
1230
1231 ((eq word 'repeat)
e542ea4b 1232 (let ((temp (make-symbol "--cl-var--")))
4dd1c416
SM
1233 (push (list (list temp (pop cl--loop-args))) cl--loop-bindings)
1234 (push `(>= (setq ,temp (1- ,temp)) 0) cl--loop-body)))
fcd73769 1235
ae1aa776 1236 ((memq word '(collect collecting))
4dd1c416
SM
1237 (let ((what (pop cl--loop-args))
1238 (var (cl--loop-handle-accum nil 'nreverse)))
1239 (if (eq var cl--loop-accum-var)
1240 (push `(progn (push ,what ,var) t) cl--loop-body)
03fef3e6
SM
1241 (push `(progn
1242 (setq ,var (nconc ,var (list ,what)))
4dd1c416 1243 t) cl--loop-body))))
fcd73769
RS
1244
1245 ((memq word '(nconc nconcing append appending))
4dd1c416
SM
1246 (let ((what (pop cl--loop-args))
1247 (var (cl--loop-handle-accum nil 'nreverse)))
03fef3e6
SM
1248 (push `(progn
1249 (setq ,var
4dd1c416 1250 ,(if (eq var cl--loop-accum-var)
03fef3e6
SM
1251 `(nconc
1252 (,(if (memq word '(nconc nconcing))
1253 #'nreverse #'reverse)
1254 ,what)
1255 ,var)
1256 `(,(if (memq word '(nconc nconcing))
1257 #'nconc #'append)
4dd1c416 1258 ,var ,what))) t) cl--loop-body)))
fcd73769
RS
1259
1260 ((memq word '(concat concating))
4dd1c416
SM
1261 (let ((what (pop cl--loop-args))
1262 (var (cl--loop-handle-accum "")))
1263 (push `(progn (cl-callf concat ,var ,what) t) cl--loop-body)))
fcd73769
RS
1264
1265 ((memq word '(vconcat vconcating))
4dd1c416
SM
1266 (let ((what (pop cl--loop-args))
1267 (var (cl--loop-handle-accum [])))
1268 (push `(progn (cl-callf vconcat ,var ,what) t) cl--loop-body)))
fcd73769
RS
1269
1270 ((memq word '(sum summing))
4dd1c416
SM
1271 (let ((what (pop cl--loop-args))
1272 (var (cl--loop-handle-accum 0)))
1273 (push `(progn (cl-incf ,var ,what) t) cl--loop-body)))
fcd73769
RS
1274
1275 ((memq word '(count counting))
4dd1c416
SM
1276 (let ((what (pop cl--loop-args))
1277 (var (cl--loop-handle-accum 0)))
1278 (push `(progn (if ,what (cl-incf ,var)) t) cl--loop-body)))
fcd73769
RS
1279
1280 ((memq word '(minimize minimizing maximize maximizing))
4dd1c416
SM
1281 (let* ((what (pop cl--loop-args))
1282 (temp (if (cl--simple-expr-p what) what (make-symbol "--cl-var--")))
1283 (var (cl--loop-handle-accum nil))
fcd73769 1284 (func (intern (substring (symbol-name word) 0 3)))
03fef3e6
SM
1285 (set `(setq ,var (if ,var (,func ,var ,temp) ,temp))))
1286 (push `(progn ,(if (eq temp what) set
1287 `(let ((,temp ,what)) ,set))
4dd1c416 1288 t) cl--loop-body)))
fcd73769
RS
1289
1290 ((eq word 'with)
1291 (let ((bindings nil))
4dd1c416
SM
1292 (while (progn (push (list (pop cl--loop-args)
1293 (and (eq (car cl--loop-args) '=) (cl-pop2 cl--loop-args)))
e542ea4b 1294 bindings)
4dd1c416
SM
1295 (eq (car cl--loop-args) 'and))
1296 (pop cl--loop-args))
1297 (push (nreverse bindings) cl--loop-bindings)))
fcd73769
RS
1298
1299 ((eq word 'while)
4dd1c416 1300 (push (pop cl--loop-args) cl--loop-body))
fcd73769
RS
1301
1302 ((eq word 'until)
4dd1c416 1303 (push `(not ,(pop cl--loop-args)) cl--loop-body))
fcd73769
RS
1304
1305 ((eq word 'always)
4dd1c416
SM
1306 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1307 (push `(setq ,cl--loop-finish-flag ,(pop cl--loop-args)) cl--loop-body)
1308 (setq cl--loop-result t))
fcd73769
RS
1309
1310 ((eq word 'never)
4dd1c416
SM
1311 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1312 (push `(setq ,cl--loop-finish-flag (not ,(pop cl--loop-args)))
1313 cl--loop-body)
1314 (setq cl--loop-result t))
fcd73769
RS
1315
1316 ((eq word 'thereis)
4dd1c416
SM
1317 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-flag--")))
1318 (or cl--loop-result-var (setq cl--loop-result-var (make-symbol "--cl-var--")))
1319 (push `(setq ,cl--loop-finish-flag
1320 (not (setq ,cl--loop-result-var ,(pop cl--loop-args))))
1321 cl--loop-body))
fcd73769
RS
1322
1323 ((memq word '(if when unless))
4dd1c416
SM
1324 (let* ((cond (pop cl--loop-args))
1325 (then (let ((cl--loop-body nil))
fcd73769 1326 (cl-parse-loop-clause)
4dd1c416
SM
1327 (cl--loop-build-ands (nreverse cl--loop-body))))
1328 (else (let ((cl--loop-body nil))
1329 (if (eq (car cl--loop-args) 'else)
1330 (progn (pop cl--loop-args) (cl-parse-loop-clause)))
1331 (cl--loop-build-ands (nreverse cl--loop-body))))
fcd73769 1332 (simple (and (eq (car then) t) (eq (car else) t))))
4dd1c416 1333 (if (eq (car cl--loop-args) 'end) (pop cl--loop-args))
fcd73769
RS
1334 (if (eq word 'unless) (setq then (prog1 else (setq else then))))
1335 (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then))
1336 (if simple (nth 1 else) (list (nth 2 else))))))
4dd1c416 1337 (if (cl--expr-contains form 'it)
e542ea4b 1338 (let ((temp (make-symbol "--cl-var--")))
4dd1c416 1339 (push (list temp) cl--loop-bindings)
03fef3e6 1340 (setq form `(if (setq ,temp ,cond)
7c1898a7 1341 ,@(cl-subst temp 'it form))))
03fef3e6 1342 (setq form `(if ,cond ,@form)))
4dd1c416 1343 (push (if simple `(progn ,form t) form) cl--loop-body))))
fcd73769
RS
1344
1345 ((memq word '(do doing))
1346 (let ((body nil))
4dd1c416
SM
1347 (or (consp (car cl--loop-args)) (error "Syntax error on `do' clause"))
1348 (while (consp (car cl--loop-args)) (push (pop cl--loop-args) body))
1349 (push (cons 'progn (nreverse (cons t body))) cl--loop-body)))
fcd73769
RS
1350
1351 ((eq word 'return)
4dd1c416
SM
1352 (or cl--loop-finish-flag (setq cl--loop-finish-flag (make-symbol "--cl-var--")))
1353 (or cl--loop-result-var (setq cl--loop-result-var (make-symbol "--cl-var--")))
1354 (push `(setq ,cl--loop-result-var ,(pop cl--loop-args)
1355 ,cl--loop-finish-flag nil) cl--loop-body))
fcd73769
RS
1356
1357 (t
4dd1c416 1358 (let ((handler (and (symbolp word) (get word 'cl--loop-handler))))
7c1898a7 1359 (or handler (error "Expected a cl-loop keyword, found %s" word))
fcd73769 1360 (funcall handler))))
4dd1c416
SM
1361 (if (eq (car cl--loop-args) 'and)
1362 (progn (pop cl--loop-args) (cl-parse-loop-clause)))))
fcd73769 1363
4dd1c416 1364(defun cl--loop-let (specs body par) ; uses loop-*
fcd73769 1365 (let ((p specs) (temps nil) (new nil))
7c1898a7 1366 (while (and p (or (symbolp (car-safe (car p))) (null (cl-cadar p))))
fcd73769
RS
1367 (setq p (cdr p)))
1368 (and par p
1369 (progn
1370 (setq par nil p specs)
1371 (while p
4dd1c416 1372 (or (macroexp-const-p (cl-cadar p))
e542ea4b 1373 (let ((temp (make-symbol "--cl-var--")))
7c1898a7 1374 (push (list temp (cl-cadar p)) temps)
fcd73769
RS
1375 (setcar (cdar p) temp)))
1376 (setq p (cdr p)))))
1377 (while specs
1378 (if (and (consp (car specs)) (listp (caar specs)))
1379 (let* ((spec (caar specs)) (nspecs nil)
69d8fb1e 1380 (expr (cadr (pop specs)))
4dd1c416 1381 (temp (cdr (or (assq spec cl--loop-destr-temps)
69d8fb1e 1382 (car (push (cons spec (or (last spec 0)
e542ea4b 1383 (make-symbol "--cl-var--")))
4dd1c416 1384 cl--loop-destr-temps))))))
69d8fb1e 1385 (push (list temp expr) new)
fcd73769 1386 (while (consp spec)
69d8fb1e 1387 (push (list (pop spec)
fcd73769
RS
1388 (and expr (list (if spec 'pop 'car) temp)))
1389 nspecs))
1390 (setq specs (nconc (nreverse nspecs) specs)))
69d8fb1e 1391 (push (pop specs) new)))
fcd73769 1392 (if (eq body 'setq)
7c1898a7 1393 (let ((set (cons (if par 'cl-psetq 'setq) (apply 'nconc (nreverse new)))))
03fef3e6
SM
1394 (if temps `(let* ,(nreverse temps) ,set) set))
1395 `(,(if par 'let 'let*)
1396 ,(nconc (nreverse temps) (nreverse new)) ,@body))))
fcd73769 1397
4dd1c416
SM
1398(defun cl--loop-handle-accum (def &optional func) ; uses loop-*
1399 (if (eq (car cl--loop-args) 'into)
1400 (let ((var (cl-pop2 cl--loop-args)))
1401 (or (memq var cl--loop-accum-vars)
1402 (progn (push (list (list var def)) cl--loop-bindings)
1403 (push var cl--loop-accum-vars)))
fcd73769 1404 var)
4dd1c416 1405 (or cl--loop-accum-var
fcd73769 1406 (progn
4dd1c416
SM
1407 (push (list (list (setq cl--loop-accum-var (make-symbol "--cl-var--")) def))
1408 cl--loop-bindings)
1409 (setq cl--loop-result (if func (list func cl--loop-accum-var)
1410 cl--loop-accum-var))
1411 cl--loop-accum-var))))
fcd73769 1412
4dd1c416 1413(defun cl--loop-build-ands (clauses)
fcd73769
RS
1414 (let ((ands nil)
1415 (body nil))
1416 (while clauses
1417 (if (and (eq (car-safe (car clauses)) 'progn)
1418 (eq (car (last (car clauses))) t))
1419 (if (cdr clauses)
1420 (setq clauses (cons (nconc (butlast (car clauses))
1421 (if (eq (car-safe (cadr clauses))
1422 'progn)
7c1898a7 1423 (cl-cdadr clauses)
fcd73769
RS
1424 (list (cadr clauses))))
1425 (cddr clauses)))
69d8fb1e
SM
1426 (setq body (cdr (butlast (pop clauses)))))
1427 (push (pop clauses) ands)))
fcd73769
RS
1428 (setq ands (or (nreverse ands) (list t)))
1429 (list (if (cdr ands) (cons 'and ands) (car ands))
1430 body
1431 (let ((full (if body
1432 (append ands (list (cons 'progn (append body '(t)))))
1433 ands)))
1434 (if (cdr full) (cons 'and full) (car full))))))
1435
1436
1437;;; Other iteration control structures.
1438
ebacfcc6 1439;;;###autoload
7c1898a7
SM
1440(defmacro cl-do (steps endtest &rest body)
1441 "The Common Lisp `cl-do' loop.
a766dfa1
JB
1442
1443\(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
70b8ef8f
SM
1444 (declare (indent 2)
1445 (debug
b1198e17
SM
1446 ((&rest &or symbolp (symbolp &optional form form))
1447 (form body)
1448 cl-declarations body)))
fcd73769
RS
1449 (cl-expand-do-loop steps endtest body nil))
1450
ebacfcc6 1451;;;###autoload
7c1898a7
SM
1452(defmacro cl-do* (steps endtest &rest body)
1453 "The Common Lisp `cl-do*' loop.
a766dfa1
JB
1454
1455\(fn ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)"
7c1898a7 1456 (declare (indent 2) (debug cl-do))
fcd73769
RS
1457 (cl-expand-do-loop steps endtest body t))
1458
1459(defun cl-expand-do-loop (steps endtest body star)
7c1898a7 1460 `(cl-block nil
03fef3e6
SM
1461 (,(if star 'let* 'let)
1462 ,(mapcar (lambda (c) (if (consp c) (list (car c) (nth 1 c)) c))
1463 steps)
1464 (while (not ,(car endtest))
1465 ,@body
1466 ,@(let ((sets (mapcar (lambda (c)
1467 (and (consp c) (cdr (cdr c))
1468 (list (car c) (nth 2 c))))
1469 steps)))
1470 (setq sets (delq nil sets))
1471 (and sets
1472 (list (cons (if (or star (not (cdr sets)))
7c1898a7 1473 'setq 'cl-psetq)
03fef3e6
SM
1474 (apply 'append sets))))))
1475 ,@(or (cdr endtest) '(nil)))))
fcd73769 1476
ebacfcc6 1477;;;###autoload
7c1898a7 1478(defmacro cl-dolist (spec &rest body)
69d8fb1e 1479 "Loop over a list.
63744c0f 1480Evaluate BODY with VAR bound to each `car' from LIST, in turn.
69d8fb1e 1481Then evaluate RESULT to get return value, default nil.
ce887515 1482An implicit nil block is established around the loop.
69d8fb1e
SM
1483
1484\(fn (VAR LIST [RESULT]) BODY...)"
a464a6c7
SM
1485 (declare (debug ((symbolp form &optional form) cl-declarations body))
1486 (indent 1))
36cec983
SM
1487 `(cl-block nil
1488 (,(if (eq 'cl-dolist (symbol-function 'dolist)) 'cl--dolist 'dolist)
1489 ,spec ,@body)))
63744c0f 1490
ebacfcc6 1491;;;###autoload
7c1898a7 1492(defmacro cl-dotimes (spec &rest body)
69d8fb1e 1493 "Loop a certain number of times.
63744c0f
DL
1494Evaluate BODY with VAR bound to successive integers from 0, inclusive,
1495to COUNT, exclusive. Then evaluate RESULT to get return value, default
69d8fb1e
SM
1496nil.
1497
1498\(fn (VAR COUNT [RESULT]) BODY...)"
a464a6c7 1499 (declare (debug cl-dolist) (indent 1))
36cec983
SM
1500 `(cl-block nil
1501 (,(if (eq 'cl-dotimes (symbol-function 'dotimes)) 'cl--dotimes 'dotimes)
1502 ,spec ,@body)))
63744c0f 1503
ebacfcc6 1504;;;###autoload
7c1898a7 1505(defmacro cl-do-symbols (spec &rest body)
69d8fb1e 1506 "Loop over all symbols.
fcd73769 1507Evaluate BODY with VAR bound to each interned symbol, or to each symbol
69d8fb1e
SM
1508from OBARRAY.
1509
1510\(fn (VAR [OBARRAY [RESULT]]) BODY...)"
70b8ef8f
SM
1511 (declare (indent 1)
1512 (debug ((symbolp &optional form form) cl-declarations body)))
fcd73769 1513 ;; Apparently this doesn't have an implicit block.
7c1898a7 1514 `(cl-block nil
03fef3e6
SM
1515 (let (,(car spec))
1516 (mapatoms #'(lambda (,(car spec)) ,@body)
1517 ,@(and (cadr spec) (list (cadr spec))))
7c1898a7 1518 ,(cl-caddr spec))))
fcd73769 1519
ebacfcc6 1520;;;###autoload
7c1898a7 1521(defmacro cl-do-all-symbols (spec &rest body)
70b8ef8f 1522 (declare (indent 1) (debug ((symbolp &optional form) cl-declarations body)))
7c1898a7 1523 `(cl-do-symbols (,(car spec) nil ,(cadr spec)) ,@body))
fcd73769
RS
1524
1525
1526;;; Assignments.
1527
ebacfcc6 1528;;;###autoload
7c1898a7 1529(defmacro cl-psetq (&rest args)
69d8fb1e 1530 "Set SYMs to the values VALs in parallel.
fcd73769 1531This is like `setq', except that all VAL forms are evaluated (in order)
69d8fb1e
SM
1532before assigning any symbols SYM to the corresponding values.
1533
1534\(fn SYM VAL SYM VAL ...)"
b1198e17 1535 (declare (debug setq))
7c1898a7 1536 (cons 'cl-psetf args))
fcd73769
RS
1537
1538
1539;;; Binding control structures.
1540
ebacfcc6 1541;;;###autoload
7c1898a7 1542(defmacro cl-progv (symbols values &rest body)
64a4c526 1543 "Bind SYMBOLS to VALUES dynamically in BODY.
fcd73769 1544The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists.
3187ba1c 1545Each symbol in the first list is bound to the corresponding value in the
fcd73769
RS
1546second list (or made unbound if VALUES is shorter than SYMBOLS); then the
1547BODY forms are executed and their result is returned. This is much like
1548a `let' form, except that the list of symbols can be computed at run-time."
70b8ef8f 1549 (declare (indent 2) (debug (form form body)))
88ecaf8f 1550 (let ((bodyfun (make-symbol "cl--progv-body"))
a464a6c7
SM
1551 (binds (make-symbol "binds"))
1552 (syms (make-symbol "syms"))
1553 (vals (make-symbol "vals")))
1554 `(progn
1555 (defvar ,bodyfun)
1556 (let* ((,syms ,symbols)
1557 (,vals ,values)
1558 (,bodyfun (lambda () ,@body))
1559 (,binds ()))
1560 (while ,syms
1561 (push (list (pop ,syms) (list 'quote (pop ,vals))) ,binds))
1562 (eval (list 'let ,binds '(funcall ,bodyfun)))))))
fcd73769 1563
de7e2b36
SM
1564(defvar cl--labels-convert-cache nil)
1565
1566(defun cl--labels-convert (f)
1567 "Special macro-expander to rename (function F) references in `cl-labels'."
1568 (cond
1569 ;; ¡¡Big Ugly Hack!! We can't use a compiler-macro because those are checked
1570 ;; *after* handling `function', but we want to stop macroexpansion from
1571 ;; being applied infinitely, so we use a cache to return the exact `form'
1572 ;; being expanded even though we don't receive it.
1573 ((eq f (car cl--labels-convert-cache)) (cdr cl--labels-convert-cache))
1574 (t
1575 (let ((found (assq f macroexpand-all-environment)))
1576 (if (and found (ignore-errors
1577 (eq (cadr (cl-caddr found)) 'cl-labels-args)))
1578 (cadr (cl-caddr (cl-cadddr found)))
1579 (let ((res `(function ,f)))
1580 (setq cl--labels-convert-cache (cons f res))
1581 res))))))
1582
ebacfcc6 1583;;;###autoload
7c1898a7 1584(defmacro cl-flet (bindings &rest body)
3187ba1c 1585 "Make temporary function definitions.
de7e2b36 1586Like `cl-labels' but the definitions are not recursive.
69d8fb1e
SM
1587
1588\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
7c1898a7 1589 (declare (indent 1) (debug ((&rest (cl-defun)) cl-declarations body)))
de7e2b36
SM
1590 (let ((binds ()) (newenv macroexpand-all-environment))
1591 (dolist (binding bindings)
1592 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1593 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1594 (push (cons (car binding)
1595 `(lambda (&rest cl-labels-args)
1596 (cl-list* 'funcall ',var
1597 cl-labels-args)))
1598 newenv)))
1599 `(let ,(nreverse binds)
1600 ,@(macroexp-unprogn
1601 (macroexpand-all
1602 `(progn ,@body)
1603 ;; Don't override lexical-let's macro-expander.
1604 (if (assq 'function newenv) newenv
1605 (cons (cons 'function #'cl--labels-convert) newenv)))))))
fcd73769 1606
d5c6faf9
SM
1607;;;###autoload
1608(defmacro cl-flet* (bindings &rest body)
1609 "Make temporary function definitions.
1610Like `cl-flet' but the definitions can refer to previous ones.
1611
1612\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
a464a6c7 1613 (declare (indent 1) (debug cl-flet))
d5c6faf9
SM
1614 (cond
1615 ((null bindings) (macroexp-progn body))
1616 ((null (cdr bindings)) `(cl-flet ,bindings ,@body))
1617 (t `(cl-flet (,(pop bindings)) (cl-flet* ,bindings ,@body)))))
1618
ebacfcc6 1619;;;###autoload
7c1898a7 1620(defmacro cl-labels (bindings &rest body)
3187ba1c 1621 "Make temporary function bindings.
a464a6c7
SM
1622The bindings can be recursive and the scoping is lexical, but capturing them
1623in closures will only work if `lexical-binding' is in use.
69d8fb1e
SM
1624
1625\(fn ((FUNC ARGLIST BODY...) ...) FORM...)"
7c1898a7 1626 (declare (indent 1) (debug cl-flet))
de7e2b36
SM
1627 (let ((binds ()) (newenv macroexpand-all-environment))
1628 (dolist (binding bindings)
1629 (let ((var (make-symbol (format "--cl-%s--" (car binding)))))
1630 (push (list var `(cl-function (lambda . ,(cdr binding)))) binds)
1631 (push (cons (car binding)
4dd1c416
SM
1632 `(lambda (&rest cl-labels-args)
1633 (cl-list* 'funcall ',var
1634 cl-labels-args)))
6fa6c4ae 1635 newenv)))
de7e2b36
SM
1636 (macroexpand-all `(letrec ,(nreverse binds) ,@body)
1637 ;; Don't override lexical-let's macro-expander.
1638 (if (assq 'function newenv) newenv
1639 (cons (cons 'function #'cl--labels-convert) newenv)))))
fcd73769
RS
1640
1641;; The following ought to have a better definition for use with newer
1642;; byte compilers.
ebacfcc6 1643;;;###autoload
7c1898a7 1644(defmacro cl-macrolet (bindings &rest body)
4342e957 1645 "Make temporary macro definitions.
7c1898a7 1646This is like `cl-flet', but for macros instead of functions.
69d8fb1e
SM
1647
1648\(fn ((NAME ARGLIST BODY...) ...) FORM...)"
70b8ef8f
SM
1649 (declare (indent 1)
1650 (debug
b1198e17
SM
1651 ((&rest (&define name (&rest arg) cl-declarations-or-string
1652 def-body))
1653 cl-declarations body)))
fcd73769 1654 (if (cdr bindings)
7c1898a7 1655 `(cl-macrolet (,(car bindings)) (cl-macrolet ,(cdr bindings) ,@body))
fcd73769
RS
1656 (if (null bindings) (cons 'progn body)
1657 (let* ((name (caar bindings))
4dd1c416 1658 (res (cl--transform-lambda (cdar bindings) name)))
fcd73769 1659 (eval (car res))
6fa6c4ae
SM
1660 (macroexpand-all (cons 'progn body)
1661 (cons (cons name `(lambda ,@(cdr res)))
1662 macroexpand-all-environment))))))
1663
1664(defconst cl--old-macroexpand
1665 (if (and (boundp 'cl--old-macroexpand)
1666 (eq (symbol-function 'macroexpand)
1667 #'cl--sm-macroexpand))
1668 cl--old-macroexpand
1669 (symbol-function 'macroexpand)))
1670
ea376861 1671(defun cl--sm-macroexpand (exp &optional env)
6fa6c4ae
SM
1672 "Special macro expander used inside `cl-symbol-macrolet'.
1673This function replaces `macroexpand' during macro expansion
1674of `cl-symbol-macrolet', and does the same thing as `macroexpand'
1675except that it additionally expands symbol macros."
ea376861 1676 (let ((macroexpand-all-environment env))
6fa6c4ae
SM
1677 (while
1678 (progn
ea376861
SM
1679 (setq exp (funcall cl--old-macroexpand exp env))
1680 (pcase exp
1681 ((pred symbolp)
1682 ;; Perform symbol-macro expansion.
1683 (when (cdr (assq (symbol-name exp) env))
1684 (setq exp (cadr (assq (symbol-name exp) env)))))
1685 (`(setq . ,_)
1686 ;; Convert setq to setf if required by symbol-macro expansion.
1687 (let* ((args (mapcar (lambda (f) (cl--sm-macroexpand f env))
1688 (cdr exp)))
1689 (p args))
1690 (while (and p (symbolp (car p))) (setq p (cddr p)))
1691 (if p (setq exp (cons 'setf args))
1692 (setq exp (cons 'setq args))
1693 ;; Don't loop further.
1694 nil)))
1695 (`(,(or `let `let*) . ,(or `(,bindings . ,body) dontcare))
1696 ;; CL's symbol-macrolet treats re-bindings as candidates for
1697 ;; expansion (turning the let into a letf if needed), contrary to
1698 ;; Common-Lisp where such re-bindings hide the symbol-macro.
1699 (let ((letf nil) (found nil) (nbs ()))
1700 (dolist (binding bindings)
1701 (let* ((var (if (symbolp binding) binding (car binding)))
1702 (sm (assq (symbol-name var) env)))
1703 (push (if (not (cdr sm))
1704 binding
1705 (let ((nexp (cadr sm)))
1706 (setq found t)
1707 (unless (symbolp nexp) (setq letf t))
1708 (cons nexp (cdr-safe binding))))
1709 nbs)))
1710 (when found
1711 (setq exp `(,(if letf
1712 (if (eq (car exp) 'let) 'cl-letf 'cl-letf*)
1713 (car exp))
1714 ,(nreverse nbs)
1715 ,@body)))))
1716 ;; FIXME: The behavior of CL made sense in a dynamically scoped
1717 ;; language, but for lexical scoping, Common-Lisp's behavior might
1718 ;; make more sense (and indeed, CL behaves like Common-Lisp w.r.t
1719 ;; lexical-let), so maybe we should adjust the behavior based on
1720 ;; the use of lexical-binding.
1721 ;; (`(,(or `let `let*) . ,(or `(,bindings . ,body) dontcare))
1722 ;; (let ((nbs ()) (found nil))
1723 ;; (dolist (binding bindings)
1724 ;; (let* ((var (if (symbolp binding) binding (car binding)))
1725 ;; (name (symbol-name var))
1726 ;; (val (and found (consp binding) (eq 'let* (car exp))
1727 ;; (list (macroexpand-all (cadr binding)
1728 ;; env)))))
1729 ;; (push (if (assq name env)
1730 ;; ;; This binding should hide its symbol-macro,
1731 ;; ;; but given the way macroexpand-all works, we
1732 ;; ;; can't prevent application of `env' to the
1733 ;; ;; sub-expressions, so we need to α-rename this
1734 ;; ;; variable instead.
1735 ;; (let ((nvar (make-symbol
1736 ;; (copy-sequence name))))
1737 ;; (setq found t)
1738 ;; (push (list name nvar) env)
1739 ;; (cons nvar (or val (cdr-safe binding))))
1740 ;; (if val (cons var val) binding))
1741 ;; nbs)))
1742 ;; (when found
1743 ;; (setq exp `(,(car exp)
1744 ;; ,(nreverse nbs)
1745 ;; ,@(macroexp-unprogn
1746 ;; (macroexpand-all (macroexp-progn body)
1747 ;; env)))))
1748 ;; nil))
1749 )))
1750 exp))
fcd73769 1751
ebacfcc6 1752;;;###autoload
7c1898a7 1753(defmacro cl-symbol-macrolet (bindings &rest body)
4342e957 1754 "Make symbol macro definitions.
fcd73769 1755Within the body FORMs, references to the variable NAME will be replaced
2ee3d7f0 1756by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...).
69d8fb1e
SM
1757
1758\(fn ((NAME EXPANSION) ...) FORM...)"
70b8ef8f 1759 (declare (indent 1) (debug ((&rest (symbol sexp)) cl-declarations body)))
6fa6c4ae
SM
1760 (cond
1761 ((cdr bindings)
36cec983 1762 `(cl-symbol-macrolet (,(car bindings))
6fa6c4ae
SM
1763 (cl-symbol-macrolet ,(cdr bindings) ,@body)))
1764 ((null bindings) (macroexp-progn body))
1765 (t
1766 (let ((previous-macroexpand (symbol-function 'macroexpand)))
1767 (unwind-protect
1768 (progn
1769 (fset 'macroexpand #'cl--sm-macroexpand)
1770 ;; FIXME: For N bindings, this will traverse `body' N times!
1771 (macroexpand-all (cons 'progn body)
36cec983
SM
1772 (cons (list (symbol-name (caar bindings))
1773 (cl-cadar bindings))
6fa6c4ae
SM
1774 macroexpand-all-environment)))
1775 (fset 'macroexpand previous-macroexpand))))))
fcd73769 1776
fcd73769
RS
1777;;; Multiple values.
1778
ebacfcc6 1779;;;###autoload
7c1898a7 1780(defmacro cl-multiple-value-bind (vars form &rest body)
69d8fb1e 1781 "Collect multiple return values.
fcd73769
RS
1782FORM must return a list; the BODY is then executed with the first N elements
1783of this list bound (`let'-style) to each of the symbols SYM in turn. This
7c1898a7
SM
1784is analogous to the Common Lisp `cl-multiple-value-bind' macro, using lists to
1785simulate true multiple return values. For compatibility, (cl-values A B C) is
69d8fb1e
SM
1786a synonym for (list A B C).
1787
3187ba1c 1788\(fn (SYM...) FORM BODY)"
70b8ef8f 1789 (declare (indent 2) (debug ((&rest symbolp) form body)))
e542ea4b 1790 (let ((temp (make-symbol "--cl-var--")) (n -1))
03fef3e6
SM
1791 `(let* ((,temp ,form)
1792 ,@(mapcar (lambda (v)
1793 (list v `(nth ,(setq n (1+ n)) ,temp)))
1794 vars))
1795 ,@body)))
fcd73769 1796
ebacfcc6 1797;;;###autoload
7c1898a7 1798(defmacro cl-multiple-value-setq (vars form)
69d8fb1e 1799 "Collect multiple return values.
fcd73769
RS
1800FORM must return a list; the first N elements of this list are stored in
1801each of the symbols SYM in turn. This is analogous to the Common Lisp
7c1898a7
SM
1802`cl-multiple-value-setq' macro, using lists to simulate true multiple return
1803values. For compatibility, (cl-values A B C) is a synonym for (list A B C).
69d8fb1e 1804
3187ba1c 1805\(fn (SYM...) FORM)"
70b8ef8f 1806 (declare (indent 1) (debug ((&rest symbolp) form)))
03fef3e6
SM
1807 (cond ((null vars) `(progn ,form nil))
1808 ((null (cdr vars)) `(setq ,(car vars) (car ,form)))
fcd73769 1809 (t
e542ea4b 1810 (let* ((temp (make-symbol "--cl-var--")) (n 0))
03fef3e6
SM
1811 `(let ((,temp ,form))
1812 (prog1 (setq ,(pop vars) (car ,temp))
1813 (setq ,@(apply #'nconc
1814 (mapcar (lambda (v)
1815 (list v `(nth ,(setq n (1+ n))
1816 ,temp)))
1817 vars)))))))))
fcd73769
RS
1818
1819
1820;;; Declarations.
1821
ebacfcc6 1822;;;###autoload
7c1898a7 1823(defmacro cl-locally (&rest body)
b1198e17
SM
1824 (declare (debug t))
1825 (cons 'progn body))
ebacfcc6 1826;;;###autoload
513749ee 1827(defmacro cl-the (_type form)
70b8ef8f 1828 (declare (indent 1) (debug (cl-type-spec form)))
b1198e17 1829 form)
fcd73769
RS
1830
1831(defvar cl-proclaim-history t) ; for future compilers
1832(defvar cl-declare-stack t) ; for future compilers
1833
1834(defun cl-do-proclaim (spec hist)
69d8fb1e 1835 (and hist (listp cl-proclaim-history) (push spec cl-proclaim-history))
fcd73769
RS
1836 (cond ((eq (car-safe spec) 'special)
1837 (if (boundp 'byte-compile-bound-variables)
1838 (setq byte-compile-bound-variables
1839 (append (cdr spec) byte-compile-bound-variables))))
1840
1841 ((eq (car-safe spec) 'inline)
1842 (while (setq spec (cdr spec))
1843 (or (memq (get (car spec) 'byte-optimizer)
1844 '(nil byte-compile-inline-expand))
1845 (error "%s already has a byte-optimizer, can't make it inline"
1846 (car spec)))
1847 (put (car spec) 'byte-optimizer 'byte-compile-inline-expand)))
1848
1849 ((eq (car-safe spec) 'notinline)
1850 (while (setq spec (cdr spec))
1851 (if (eq (get (car spec) 'byte-optimizer)
1852 'byte-compile-inline-expand)
1853 (put (car spec) 'byte-optimizer nil))))
1854
1855 ((eq (car-safe spec) 'optimize)
1856 (let ((speed (assq (nth 1 (assq 'speed (cdr spec)))
1857 '((0 nil) (1 t) (2 t) (3 t))))
1858 (safety (assq (nth 1 (assq 'safety (cdr spec)))
1859 '((0 t) (1 t) (2 t) (3 nil)))))
1860 (if speed (setq cl-optimize-speed (car speed)
1861 byte-optimize (nth 1 speed)))
1862 (if safety (setq cl-optimize-safety (car safety)
1863 byte-compile-delete-errors (nth 1 safety)))))
1864
1865 ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings))
fcd73769
RS
1866 (while (setq spec (cdr spec))
1867 (if (consp (car spec))
7c1898a7 1868 (if (eq (cl-cadar spec) 0)
bc8ce89b
GM
1869 (byte-compile-disable-warning (caar spec))
1870 (byte-compile-enable-warning (caar spec)))))))
fcd73769
RS
1871 nil)
1872
1873;;; Process any proclamations made before cl-macs was loaded.
1874(defvar cl-proclaims-deferred)
1875(let ((p (reverse cl-proclaims-deferred)))
69d8fb1e 1876 (while p (cl-do-proclaim (pop p) t))
fcd73769
RS
1877 (setq cl-proclaims-deferred nil))
1878
ebacfcc6 1879;;;###autoload
7c1898a7 1880(defmacro cl-declare (&rest specs)
c39da690 1881 "Declare SPECS about the current function while compiling.
4bf0979f
LMI
1882For instance
1883
7c1898a7 1884 \(cl-declare (warn 0))
4bf0979f 1885
dbc44fcd
LMI
1886will turn off byte-compile warnings in the function.
1887See Info node `(cl)Declarations' for details."
bb3faf5b 1888 (if (cl--compiling-file)
fcd73769 1889 (while specs
69d8fb1e
SM
1890 (if (listp cl-declare-stack) (push (car specs) cl-declare-stack))
1891 (cl-do-proclaim (pop specs) nil)))
fcd73769
RS
1892 nil)
1893
1894
1895
fcd73769 1896;;; The standard modify macros.
69d8fb1e 1897
2ee3d7f0 1898;; `setf' is now part of core Elisp, defined in gv.el.
fcd73769 1899
ebacfcc6 1900;;;###autoload
7c1898a7 1901(defmacro cl-psetf (&rest args)
69d8fb1e 1902 "Set PLACEs to the values VALs in parallel.
2ee3d7f0 1903This is like `setf', except that all VAL forms are evaluated (in order)
69d8fb1e
SM
1904before assigning any PLACEs to the corresponding values.
1905
1906\(fn PLACE VAL PLACE VAL ...)"
2ee3d7f0 1907 (declare (debug setf))
fcd73769
RS
1908 (let ((p args) (simple t) (vars nil))
1909 (while p
4dd1c416 1910 (if (or (not (symbolp (car p))) (cl--expr-depends-p (nth 1 p) vars))
fcd73769
RS
1911 (setq simple nil))
1912 (if (memq (car p) vars)
1913 (error "Destination duplicated in psetf: %s" (car p)))
69d8fb1e 1914 (push (pop p) vars)
7c1898a7 1915 (or p (error "Odd number of arguments to cl-psetf"))
69d8fb1e 1916 (pop p))
fcd73769 1917 (if simple
2ee3d7f0 1918 `(progn (setf ,@args) nil)
fcd73769 1919 (setq args (reverse args))
2ee3d7f0 1920 (let ((expr `(setf ,(cadr args) ,(car args))))
fcd73769 1921 (while (setq args (cddr args))
2ee3d7f0 1922 (setq expr `(setf ,(cadr args) (prog1 ,(car args) ,expr))))
03fef3e6 1923 `(progn ,expr nil)))))
fcd73769 1924
ebacfcc6 1925;;;###autoload
7c1898a7 1926(defmacro cl-remf (place tag)
64a4c526 1927 "Remove TAG from property list PLACE.
2ee3d7f0 1928PLACE may be a symbol, or any generalized variable allowed by `setf'.
fcd73769 1929The form returns true if TAG was found and removed, nil otherwise."
b1198e17 1930 (declare (debug (place form)))
2ee3d7f0
SM
1931 (gv-letplace (tval setter) place
1932 (macroexp-let2 macroexp-copyable-p ttag tag
1933 `(if (eq ,ttag (car ,tval))
1934 (progn ,(funcall setter `(cddr ,tval))
03fef3e6 1935 t)
ad4d226c 1936 (cl--do-remf ,tval ,ttag)))))
fcd73769 1937
ebacfcc6 1938;;;###autoload
7c1898a7 1939(defmacro cl-shiftf (place &rest args)
69d8fb1e 1940 "Shift left among PLACEs.
7c1898a7 1941Example: (cl-shiftf A B C) sets A to B, B to C, and returns the old A.
2ee3d7f0 1942Each PLACE may be a symbol, or any generalized variable allowed by `setf'.
69d8fb1e 1943
3187ba1c 1944\(fn PLACE... VAL)"
b1198e17 1945 (declare (debug (&rest place)))
2fa5eef4
SM
1946 (cond
1947 ((null args) place)
7c1898a7 1948 ((symbolp place) `(prog1 ,place (setq ,place (cl-shiftf ,@args))))
2fa5eef4 1949 (t
2ee3d7f0
SM
1950 (gv-letplace (getter setter) place
1951 `(prog1 ,getter
1952 ,(funcall setter `(cl-shiftf ,@args)))))))
fcd73769 1953
ebacfcc6 1954;;;###autoload
7c1898a7 1955(defmacro cl-rotatef (&rest args)
69d8fb1e 1956 "Rotate left among PLACEs.
7c1898a7 1957Example: (cl-rotatef A B C) sets A to B, B to C, and C to A. It returns nil.
2ee3d7f0 1958Each PLACE may be a symbol, or any generalized variable allowed by `setf'.
69d8fb1e
SM
1959
1960\(fn PLACE...)"
b1198e17 1961 (declare (debug (&rest place)))
fcd73769
RS
1962 (if (not (memq nil (mapcar 'symbolp args)))
1963 (and (cdr args)
1964 (let ((sets nil)
1965 (first (car args)))
1966 (while (cdr args)
69d8fb1e 1967 (setq sets (nconc sets (list (pop args) (car args)))))
7c1898a7 1968 `(cl-psetf ,@sets ,(car args) ,first)))
fcd73769 1969 (let* ((places (reverse args))
e542ea4b 1970 (temp (make-symbol "--cl-rotatef--"))
fcd73769
RS
1971 (form temp))
1972 (while (cdr places)
2ee3d7f0
SM
1973 (setq form
1974 (gv-letplace (getter setter) (pop places)
1975 `(prog1 ,getter ,(funcall setter form)))))
1976 (gv-letplace (getter setter) (car places)
1977 (macroexp-let* `((,temp ,getter))
1978 `(progn ,(funcall setter form) nil))))))
fcd73769 1979
a464a6c7
SM
1980;; FIXME: `letf' is unsatisfactory because it does not really "restore" the
1981;; previous state. If the getter/setter loses information, that info is
1982;; not recovered.
1983
1984(defun cl--letf (bindings simplebinds binds body)
1985 ;; It's not quite clear what the semantics of cl-letf should be.
1986 ;; E.g. in (cl-letf ((PLACE1 VAL1) (PLACE2 VAL2)) BODY), while it's clear
1987 ;; that the actual assignments ("bindings") should only happen after
1988 ;; evaluating VAL1 and VAL2, it's not clear when the sub-expressions of
1989 ;; PLACE1 and PLACE2 should be evaluated. Should we have
1990 ;; PLACE1; VAL1; PLACE2; VAL2; bind1; bind2
1991 ;; or
1992 ;; VAL1; VAL2; PLACE1; PLACE2; bind1; bind2
1993 ;; or
1994 ;; VAL1; VAL2; PLACE1; bind1; PLACE2; bind2
1995 ;; Common-Lisp's `psetf' does the first, so we'll do the same.
1996 (if (null bindings)
1997 (if (and (null binds) (null simplebinds)) (macroexp-progn body)
1998 `(let* (,@(mapcar (lambda (x)
1999 (pcase-let ((`(,vold ,getter ,_setter ,_vnew) x))
2000 (list vold getter)))
2001 binds)
2002 ,@simplebinds)
2003 (unwind-protect
2004 ,(macroexp-progn
2005 (append
2006 (delq nil
2007 (mapcar (lambda (x)
2008 (pcase x
2009 ;; If there's no vnew, do nothing.
2010 (`(,_vold ,_getter ,setter ,vnew)
2011 (funcall setter vnew))))
2012 binds))
2013 body))
2014 ,@(mapcar (lambda (x)
2015 (pcase-let ((`(,vold ,_getter ,setter ,_vnew) x))
2016 (funcall setter vold)))
2017 binds))))
2018 (let ((binding (car bindings)))
2019 (gv-letplace (getter setter) (car binding)
2020 (macroexp-let2 nil vnew (cadr binding)
2021 (if (symbolp (car binding))
2022 ;; Special-case for simple variables.
2023 (cl--letf (cdr bindings)
2024 (cons `(,getter ,(if (cdr binding) vnew getter))
2025 simplebinds)
2026 binds body)
2027 (cl--letf (cdr bindings) simplebinds
2028 (cons `(,(make-symbol "old") ,getter ,setter
2029 ,@(if (cdr binding) (list vnew)))
2030 binds)
2031 body)))))))
2032
2033;;;###autoload
2034(defmacro cl-letf (bindings &rest body)
2035 "Temporarily bind to PLACEs.
2036This is the analogue of `let', but with generalized variables (in the
2037sense of `setf') for the PLACEs. Each PLACE is set to the corresponding
2038VALUE, then the BODY forms are executed. On exit, either normally or
2039because of a `throw' or error, the PLACEs are set back to their original
2040values. Note that this macro is *not* available in Common Lisp.
2041As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)',
2042the PLACE is not modified before executing BODY.
2043
2044\(fn ((PLACE VALUE) ...) BODY...)"
2045 (declare (indent 1) (debug ((&rest (gate gv-place &optional form)) body)))
2046 (if (and (not (cdr bindings)) (cdar bindings) (symbolp (caar bindings)))
2047 `(let ,bindings ,@body)
2048 (cl--letf bindings () () body)))
2049
2050;;;###autoload
2051(defmacro cl-letf* (bindings &rest body)
2052 "Temporarily bind to PLACEs.
2053Like `cl-letf' but where the bindings are performed one at a time,
2054rather than all at the end (i.e. like `let*' rather than like `let')."
2055 (declare (indent 1) (debug cl-letf))
2056 (dolist (binding (reverse bindings))
2057 (setq body (list `(cl-letf (,binding) ,@body))))
2058 (macroexp-progn body))
2059
ebacfcc6 2060;;;###autoload
7c1898a7 2061(defmacro cl-callf (func place &rest args)
69d8fb1e 2062 "Set PLACE to (FUNC PLACE ARGS...).
fcd73769 2063FUNC should be an unquoted function name. PLACE may be a symbol,
2ee3d7f0 2064or any generalized variable allowed by `setf'."
7c1898a7 2065 (declare (indent 2) (debug (cl-function place &rest form)))
2ee3d7f0
SM
2066 (gv-letplace (getter setter) place
2067 (let* ((rargs (cons getter args)))
2068 (funcall setter
2069 (if (symbolp func) (cons func rargs)
2070 `(funcall #',func ,@rargs))))))
fcd73769 2071
ebacfcc6 2072;;;###autoload
7c1898a7 2073(defmacro cl-callf2 (func arg1 place &rest args)
69d8fb1e 2074 "Set PLACE to (FUNC ARG1 PLACE ARGS...).
7c1898a7 2075Like `cl-callf', but PLACE is the second argument of FUNC, not the first.
69d8fb1e
SM
2076
2077\(fn FUNC ARG1 PLACE ARGS...)"
7c1898a7 2078 (declare (indent 3) (debug (cl-function form place &rest form)))
4dd1c416 2079 (if (and (cl--safe-expr-p arg1) (cl--simple-expr-p place) (symbolp func))
2ee3d7f0
SM
2080 `(setf ,place (,func ,arg1 ,place ,@args))
2081 (macroexp-let2 nil a1 arg1
2082 (gv-letplace (getter setter) place
2083 (let* ((rargs (cl-list* a1 getter args)))
2084 (funcall setter
2085 (if (symbolp func) (cons func rargs)
2086 `(funcall #',func ,@rargs))))))))
fcd73769
RS
2087
2088;;; Structures.
2089
ebacfcc6 2090;;;###autoload
7c1898a7 2091(defmacro cl-defstruct (struct &rest descs)
69d8fb1e 2092 "Define a struct type.
c7dc1ac1
CY
2093This macro defines a new data type called NAME that stores data
2094in SLOTs. It defines a `make-NAME' constructor, a `copy-NAME'
2095copier, a `NAME-p' predicate, and slot accessors named `NAME-SLOT'.
2ee3d7f0 2096You can use the accessors to set the corresponding slots, via `setf'.
69d8fb1e 2097
c7dc1ac1
CY
2098NAME may instead take the form (NAME OPTIONS...), where each
2099OPTION is either a single keyword or (KEYWORD VALUE).
2100See Info node `(cl)Structures' for a list of valid keywords.
2101
2102Each SLOT may instead take the form (SLOT SLOT-OPTS...), where
2103SLOT-OPTS are keyword-value pairs for that slot. Currently, only
2104one keyword is supported, `:read-only'. If this has a non-nil
2ee3d7f0 2105value, that slot cannot be set via `setf'.
c7dc1ac1
CY
2106
2107\(fn NAME SLOTS...)"
b581bb5c
SM
2108 (declare (doc-string 2)
2109 (debug
b1198e17
SM
2110 (&define ;Makes top-level form not be wrapped.
2111 [&or symbolp
2112 (gate
2113 symbolp &rest
2114 (&or [":conc-name" symbolp]
2115 [":constructor" symbolp &optional cl-lambda-list]
2116 [":copier" symbolp]
2117 [":predicate" symbolp]
2118 [":include" symbolp &rest sexp] ;; Not finished.
2119 ;; The following are not supported.
2120 ;; [":print-function" ...]
2121 ;; [":type" ...]
2122 ;; [":initial-offset" ...]
2123 ))]
2124 [&optional stringp]
2125 ;; All the above is for the following def-form.
2126 &rest &or symbolp (symbolp def-form
2127 &optional ":read-only" sexp))))
fcd73769
RS
2128 (let* ((name (if (consp struct) (car struct) struct))
2129 (opts (cdr-safe struct))
2130 (slots nil)
2131 (defaults nil)
2132 (conc-name (concat (symbol-name name) "-"))
2133 (constructor (intern (format "make-%s" name)))
2134 (constrs nil)
2135 (copier (intern (format "copy-%s" name)))
2136 (predicate (intern (format "%s-p" name)))
2137 (print-func nil) (print-auto nil)
bb3faf5b 2138 (safety (if (cl--compiling-file) cl-optimize-safety 3))
fcd73769
RS
2139 (include nil)
2140 (tag (intern (format "cl-struct-%s" name)))
2141 (tag-symbol (intern (format "cl-struct-%s-tags" name)))
2142 (include-descs nil)
fcd73769
RS
2143 (side-eff nil)
2144 (type nil)
2145 (named nil)
2146 (forms nil)
2147 pred-form pred-check)
2148 (if (stringp (car descs))
03fef3e6
SM
2149 (push `(put ',name 'structure-documentation
2150 ,(pop descs)) forms))
fcd73769
RS
2151 (setq descs (cons '(cl-tag-slot)
2152 (mapcar (function (lambda (x) (if (consp x) x (list x))))
2153 descs)))
2154 (while opts
2155 (let ((opt (if (consp (car opts)) (caar opts) (car opts)))
69d8fb1e 2156 (args (cdr-safe (pop opts))))
64a4c526 2157 (cond ((eq opt :conc-name)
fcd73769
RS
2158 (if args
2159 (setq conc-name (if (car args)
2160 (symbol-name (car args)) ""))))
64a4c526 2161 ((eq opt :constructor)
fcd73769 2162 (if (cdr args)
40e8a6c3
SM
2163 (progn
2164 ;; If this defines a constructor of the same name as
2165 ;; the default one, don't define the default.
2166 (if (eq (car args) constructor)
2167 (setq constructor nil))
2168 (push args constrs))
fcd73769 2169 (if args (setq constructor (car args)))))
64a4c526 2170 ((eq opt :copier)
fcd73769 2171 (if args (setq copier (car args))))
64a4c526 2172 ((eq opt :predicate)
fcd73769 2173 (if args (setq predicate (car args))))
64a4c526 2174 ((eq opt :include)
fcd73769
RS
2175 (setq include (car args)
2176 include-descs (mapcar (function
2177 (lambda (x)
2178 (if (consp x) x (list x))))
36f0f2b1 2179 (cdr args))))
64a4c526 2180 ((eq opt :print-function)
fcd73769 2181 (setq print-func (car args)))
64a4c526 2182 ((eq opt :type)
fcd73769 2183 (setq type (car args)))
64a4c526 2184 ((eq opt :named)
fcd73769 2185 (setq named t))
64a4c526 2186 ((eq opt :initial-offset)
fcd73769
RS
2187 (setq descs (nconc (make-list (car args) '(cl-skip-slot))
2188 descs)))
2189 (t
2190 (error "Slot option %s unrecognized" opt)))))
2191 (if print-func
03fef3e6
SM
2192 (setq print-func
2193 `(progn (funcall #',print-func cl-x cl-s cl-n) t))
fcd73769
RS
2194 (or type (and include (not (get include 'cl-struct-print)))
2195 (setq print-auto t
2196 print-func (and (or (not (or include type)) (null print-func))
03fef3e6
SM
2197 `(progn
2198 (princ ,(format "#S(%s" name) cl-s))))))
fcd73769
RS
2199 (if include
2200 (let ((inc-type (get include 'cl-struct-type))
2201 (old-descs (get include 'cl-struct-slots)))
2202 (or inc-type (error "%s is not a struct name" include))
2203 (and type (not (eq (car inc-type) type))
2204 (error ":type disagrees with :include for %s" name))
2205 (while include-descs
2206 (setcar (memq (or (assq (caar include-descs) old-descs)
2207 (error "No slot %s in included struct %s"
2208 (caar include-descs) include))
2209 old-descs)
69d8fb1e 2210 (pop include-descs)))
fcd73769
RS
2211 (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs))
2212 type (car inc-type)
2213 named (assq 'cl-tag-slot descs))
2214 (if (cadr inc-type) (setq tag name named t))
36f0f2b1
RS
2215 (let ((incl include))
2216 (while incl
7c1898a7 2217 (push `(cl-pushnew ',tag
03fef3e6
SM
2218 ,(intern (format "cl-struct-%s-tags" incl)))
2219 forms)
36f0f2b1 2220 (setq incl (get incl 'cl-struct-include)))))
fcd73769
RS
2221 (if type
2222 (progn
2223 (or (memq type '(vector list))
4920bd1e 2224 (error "Invalid :type specifier: %s" type))
fcd73769
RS
2225 (if named (setq tag name)))
2226 (setq type 'vector named 'true)))
2227 (or named (setq descs (delq (assq 'cl-tag-slot descs) descs)))
03fef3e6 2228 (push `(defvar ,tag-symbol) forms)
fcd73769
RS
2229 (setq pred-form (and named
2230 (let ((pos (- (length descs)
2231 (length (memq (assq 'cl-tag-slot descs)
2232 descs)))))
2233 (if (eq type 'vector)
03fef3e6
SM
2234 `(and (vectorp cl-x)
2235 (>= (length cl-x) ,(length descs))
2236 (memq (aref cl-x ,pos) ,tag-symbol))
fcd73769 2237 (if (= pos 0)
03fef3e6
SM
2238 `(memq (car-safe cl-x) ,tag-symbol)
2239 `(and (consp cl-x)
2240 (memq (nth ,pos cl-x) ,tag-symbol))))))
fcd73769 2241 pred-check (and pred-form (> safety 0)
7c1898a7 2242 (if (and (eq (cl-caadr pred-form) 'vectorp)
fcd73769 2243 (= safety 1))
7c1898a7 2244 (cons 'and (cl-cdddr pred-form)) pred-form)))
fcd73769
RS
2245 (let ((pos 0) (descp descs))
2246 (while descp
69d8fb1e 2247 (let* ((desc (pop descp))
fcd73769
RS
2248 (slot (car desc)))
2249 (if (memq slot '(cl-tag-slot cl-skip-slot))
2250 (progn
69d8fb1e 2251 (push nil slots)
03fef3e6 2252 (push (and (eq slot 'cl-tag-slot) `',tag)
fcd73769
RS
2253 defaults))
2254 (if (assq slot descp)
2255 (error "Duplicate slots named %s in %s" slot name))
2256 (let ((accessor (intern (format "%s%s" conc-name slot))))
69d8fb1e
SM
2257 (push slot slots)
2258 (push (nth 1 desc) defaults)
2ee3d7f0
SM
2259 (push `(cl-defsubst ,accessor (cl-x)
2260 ,@(and pred-check
03fef3e6
SM
2261 (list `(or ,pred-check
2262 (error "%s accessing a non-%s"
2263 ',accessor ',name))))
2ee3d7f0
SM
2264 ,(if (eq type 'vector) `(aref cl-x ,pos)
2265 (if (= pos 0) '(car cl-x)
2266 `(nth ,pos cl-x)))) forms)
69d8fb1e 2267 (push (cons accessor t) side-eff)
2ee3d7f0
SM
2268 ;; Don't bother defining a setf-expander, since gv-get can use
2269 ;; the compiler macro to get the same result.
2270 ;;(push `(gv-define-setter ,accessor (cl-val cl-x)
2271 ;; ,(if (cadr (memq :read-only (cddr desc)))
2272 ;; `(progn (ignore cl-x cl-val)
2273 ;; (error "%s is a read-only slot"
2274 ;; ',accessor))
2275 ;; ;; If cl is loaded only for compilation,
2276 ;; ;; the call to cl--struct-setf-expander would
2277 ;; ;; cause a warning because it may not be
2278 ;; ;; defined at run time. Suppress that warning.
2279 ;; `(progn
2280 ;; (declare-function
2281 ;; cl--struct-setf-expander "cl-macs"
2282 ;; (x name accessor pred-form pos))
2283 ;; (cl--struct-setf-expander
2284 ;; cl-val cl-x ',name ',accessor
2285 ;; ,(and pred-check `',pred-check)
2286 ;; ,pos))))
2287 ;; forms)
fcd73769
RS
2288 (if print-auto
2289 (nconc print-func
03fef3e6
SM
2290 (list `(princ ,(format " %s" slot) cl-s)
2291 `(prin1 (,accessor cl-x) cl-s)))))))
fcd73769
RS
2292 (setq pos (1+ pos))))
2293 (setq slots (nreverse slots)
2294 defaults (nreverse defaults))
2295 (and predicate pred-form
7c1898a7 2296 (progn (push `(cl-defsubst ,predicate (cl-x)
03fef3e6
SM
2297 ,(if (eq (car pred-form) 'and)
2298 (append pred-form '(t))
2299 `(and ,pred-form t))) forms)
69d8fb1e 2300 (push (cons predicate 'error-free) side-eff)))
fcd73769 2301 (and copier
03fef3e6 2302 (progn (push `(defun ,copier (x) (copy-sequence x)) forms)
69d8fb1e 2303 (push (cons copier t) side-eff)))
fcd73769 2304 (if constructor
69d8fb1e 2305 (push (list constructor
fcd73769
RS
2306 (cons '&key (delq nil (copy-sequence slots))))
2307 constrs))
2308 (while constrs
2309 (let* ((name (caar constrs))
69d8fb1e 2310 (args (cadr (pop constrs)))
4dd1c416 2311 (anames (cl--arglist-args args))
7c1898a7 2312 (make (cl-mapcar (function (lambda (s d) (if (memq s anames) s d)))
fcd73769 2313 slots defaults)))
7c1898a7 2314 (push `(cl-defsubst ,name
03fef3e6
SM
2315 (&cl-defs '(nil ,@descs) ,@args)
2316 (,type ,@make)) forms)
4dd1c416 2317 (if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs)))
69d8fb1e 2318 (push (cons name t) side-eff))))
fcd73769 2319 (if print-auto (nconc print-func (list '(princ ")" cl-s) t)))
5a315f9c
SM
2320 ;; Don't bother adding to cl-custom-print-functions since it's not used
2321 ;; by anything anyway!
2322 ;;(if print-func
2323 ;; (push `(if (boundp 'cl-custom-print-functions)
2324 ;; (push
2325 ;; ;; The auto-generated function does not pay attention to
2326 ;; ;; the depth argument cl-n.
2327 ;; (lambda (cl-x cl-s ,(if print-auto '_cl-n 'cl-n))
2328 ;; (and ,pred-form ,print-func))
2329 ;; cl-custom-print-functions))
2330 ;; forms))
03fef3e6 2331 (push `(setq ,tag-symbol (list ',tag)) forms)
7c1898a7 2332 (push `(cl-eval-when (compile load eval)
03fef3e6
SM
2333 (put ',name 'cl-struct-slots ',descs)
2334 (put ',name 'cl-struct-type ',(list type (eq named t)))
2335 (put ',name 'cl-struct-include ',include)
2336 (put ',name 'cl-struct-print ,print-auto)
2337 ,@(mapcar (lambda (x)
2338 `(put ',(car x) 'side-effect-free ',(cdr x)))
2339 side-eff))
2340 forms)
2341 `(progn ,@(nreverse (cons `',name forms)))))
fcd73769 2342
fcd73769
RS
2343;;; Types and assertions.
2344
15120dec 2345;;;###autoload
7c1898a7 2346(defmacro cl-deftype (name arglist &rest body)
64a4c526 2347 "Define NAME as a new data type.
7c1898a7
SM
2348The type name can then be used in `cl-typecase', `cl-check-type', etc."
2349 (declare (debug cl-defmacro) (doc-string 3))
2350 `(cl-eval-when (compile load eval)
4302f5ba
SM
2351 (put ',name 'cl-deftype-handler
2352 (cl-function (lambda (&cl-defs '('*) ,@arglist) ,@body)))))
fcd73769 2353
4dd1c416 2354(defun cl--make-type-test (val type)
fcd73769
RS
2355 (if (symbolp type)
2356 (cond ((get type 'cl-deftype-handler)
4dd1c416 2357 (cl--make-type-test val (funcall (get type 'cl-deftype-handler))))
fcd73769 2358 ((memq type '(nil t)) type)
e0b16322 2359 ((eq type 'null) `(null ,val))
578f8106 2360 ((eq type 'atom) `(atom ,val))
7c1898a7 2361 ((eq type 'float) `(cl-floatp-safe ,val))
e0b16322
SM
2362 ((eq type 'real) `(numberp ,val))
2363 ((eq type 'fixnum) `(integerp ,val))
7c1898a7 2364 ;; FIXME: Should `character' accept things like ?\C-\M-a ? --Stef
31ff0ac1 2365 ((memq type '(character string-char)) `(characterp ,val))
fcd73769
RS
2366 (t
2367 (let* ((name (symbol-name type))
2368 (namep (intern (concat name "p"))))
2369 (if (fboundp namep) (list namep val)
2370 (list (intern (concat name "-p")) val)))))
2371 (cond ((get (car type) 'cl-deftype-handler)
4dd1c416 2372 (cl--make-type-test val (apply (get (car type) 'cl-deftype-handler)
fcd73769 2373 (cdr type))))
e0b16322 2374 ((memq (car type) '(integer float real number))
4dd1c416 2375 (delq t `(and ,(cl--make-type-test val (car type))
03fef3e6 2376 ,(if (memq (cadr type) '(* nil)) t
7c1898a7 2377 (if (consp (cadr type)) `(> ,val ,(cl-caadr type))
03fef3e6 2378 `(>= ,val ,(cadr type))))
7c1898a7
SM
2379 ,(if (memq (cl-caddr type) '(* nil)) t
2380 (if (consp (cl-caddr type)) `(< ,val ,(cl-caaddr type))
2381 `(<= ,val ,(cl-caddr type)))))))
e0b16322 2382 ((memq (car type) '(and or not))
fcd73769 2383 (cons (car type)
4dd1c416 2384 (mapcar (function (lambda (x) (cl--make-type-test val x)))
fcd73769 2385 (cdr type))))
7c1898a7
SM
2386 ((memq (car type) '(member cl-member))
2387 `(and (cl-member ,val ',(cdr type)) t))
e0b16322 2388 ((eq (car type) 'satisfies) (list (cadr type) val))
fcd73769
RS
2389 (t (error "Bad type spec: %s" type)))))
2390
513749ee 2391(defvar cl--object)
ebacfcc6 2392;;;###autoload
7c1898a7 2393(defun cl-typep (object type) ; See compiler macro below.
fcd73769
RS
2394 "Check that OBJECT is of type TYPE.
2395TYPE is a Common Lisp-style type specifier."
513749ee
SM
2396 (let ((cl--object object)) ;; Yuck!!
2397 (eval (cl--make-type-test 'cl--object type))))
fcd73769 2398
ebacfcc6 2399;;;###autoload
7c1898a7 2400(defmacro cl-check-type (form type &optional string)
fcd73769
RS
2401 "Verify that FORM is of type TYPE; signal an error if not.
2402STRING is an optional description of the desired type."
b1198e17 2403 (declare (debug (place cl-type-spec &optional stringp)))
bb3faf5b 2404 (and (or (not (cl--compiling-file))
fcd73769 2405 (< cl-optimize-speed 3) (= cl-optimize-safety 3))
4dd1c416 2406 (let* ((temp (if (cl--simple-expr-p form 3)
e542ea4b 2407 form (make-symbol "--cl-var--")))
4dd1c416 2408 (body `(or ,(cl--make-type-test temp type)
03fef3e6
SM
2409 (signal 'wrong-type-argument
2410 (list ,(or string `',type)
2411 ,temp ',form)))))
2412 (if (eq temp form) `(progn ,body nil)
2413 `(let ((,temp ,form)) ,body nil)))))
fcd73769 2414
ebacfcc6 2415;;;###autoload
7c1898a7 2416(defmacro cl-assert (form &optional show-args string &rest args)
d5c6faf9 2417 ;; FIXME: This is actually not compatible with Common-Lisp's `assert'.
fcd73769
RS
2418 "Verify that FORM returns non-nil; signal an error if not.
2419Second arg SHOW-ARGS means to include arguments of FORM in message.
2420Other args STRING and ARGS... are arguments to be passed to `error'.
2421They are not evaluated unless the assertion fails. If STRING is
2422omitted, a default message listing FORM itself is used."
b1198e17 2423 (declare (debug (form &rest form)))
bb3faf5b 2424 (and (or (not (cl--compiling-file))
fcd73769 2425 (< cl-optimize-speed 3) (= cl-optimize-safety 3))
2b88d62a 2426 (let ((sargs (and show-args
4dd1c416
SM
2427 (delq nil (mapcar (lambda (x)
2428 (unless (macroexp-const-p x)
2429 x))
2430 (cdr form))))))
03fef3e6
SM
2431 `(progn
2432 (or ,form
2433 ,(if string
2434 `(error ,string ,@sargs ,@args)
2435 `(signal 'cl-assertion-failed
2436 (list ',form ,@sargs))))
2437 nil))))
fcd73769 2438
fcd73769
RS
2439;;; Compiler macros.
2440
ebacfcc6 2441;;;###autoload
7c1898a7 2442(defmacro cl-define-compiler-macro (func args &rest body)
64a4c526 2443 "Define a compiler-only macro.
fcd73769
RS
2444This is like `defmacro', but macro expansion occurs only if the call to
2445FUNC is compiled (i.e., not interpreted). Compiler macros should be used
2446for optimizing the way calls to FUNC are compiled; the form returned by
2447BODY should do the same thing as a call to the normal function called
2448FUNC, though possibly more efficiently. Note that, like regular macros,
2449compiler macros are expanded repeatedly until no further expansions are
2450possible. Unlike regular macros, BODY can decide to \"punt\" and leave the
2451original function call alone by declaring an initial `&whole foo' parameter
2452and then returning foo."
7c1898a7 2453 (declare (debug cl-defmacro))
16c9c10f 2454 (let ((p args) (res nil))
69d8fb1e 2455 (while (consp p) (push (pop p) res))
16c9c10f 2456 (setq args (nconc (nreverse res) (and p (list '&rest p)))))
7c1898a7 2457 `(cl-eval-when (compile load eval)
4302f5ba
SM
2458 (put ',func 'compiler-macro
2459 (cl-function (lambda ,(if (memq '&whole args) (delq '&whole args)
2460 (cons '_cl-whole-arg args))
2461 ,@body)))
57a7d507
SM
2462 ;; This is so that describe-function can locate
2463 ;; the macro definition.
2464 (let ((file ,(or buffer-file-name
2465 (and (boundp 'byte-compile-current-file)
2466 (stringp byte-compile-current-file)
2467 byte-compile-current-file))))
2468 (if file (put ',func 'compiler-macro-file
2469 (purecopy (file-name-nondirectory file)))))))
fcd73769 2470
ebacfcc6 2471;;;###autoload
7c1898a7 2472(defun cl-compiler-macroexpand (form)
fcd73769
RS
2473 (while
2474 (let ((func (car-safe form)) (handler nil))
2475 (while (and (symbolp func)
57a7d507 2476 (not (setq handler (get func 'compiler-macro)))
fcd73769 2477 (fboundp func)
7abaf5cc
SM
2478 (or (not (autoloadp (symbol-function func)))
2479 (autoload-do-load (symbol-function func) func)))
fcd73769
RS
2480 (setq func (symbol-function func)))
2481 (and handler
2482 (not (eq form (setq form (apply handler form (cdr form))))))))
2483 form)
2484
414dbb00
SM
2485;; Optimize away unused block-wrappers.
2486
4dd1c416 2487(defvar cl--active-block-names nil)
414dbb00 2488
bb3faf5b 2489(cl-define-compiler-macro cl--block-wrapper (cl-form)
414dbb00 2490 (let* ((cl-entry (cons (nth 1 (nth 1 cl-form)) nil))
4dd1c416 2491 (cl--active-block-names (cons cl-entry cl--active-block-names))
414dbb00
SM
2492 (cl-body (macroexpand-all ;Performs compiler-macro expansions.
2493 (cons 'progn (cddr cl-form))
2494 macroexpand-all-environment)))
2495 ;; FIXME: To avoid re-applying macroexpand-all, we'd like to be able
2496 ;; to indicate that this return value is already fully expanded.
2497 (if (cdr cl-entry)
a08a25d7 2498 `(catch ,(nth 1 cl-form) ,@(cdr cl-body))
414dbb00
SM
2499 cl-body)))
2500
bb3faf5b 2501(cl-define-compiler-macro cl--block-throw (cl-tag cl-value)
4dd1c416 2502 (let ((cl-found (assq (nth 1 cl-tag) cl--active-block-names)))
414dbb00
SM
2503 (if cl-found (setcdr cl-found t)))
2504 `(throw ,cl-tag ,cl-value))
2505
eb123b12 2506;;;###autoload
7c1898a7 2507(defmacro cl-defsubst (name args &rest body)
69d8fb1e 2508 "Define NAME as a function.
fcd73769
RS
2509Like `defun', except the function is automatically declared `inline',
2510ARGLIST allows full Common Lisp conventions, and BODY is implicitly
7c1898a7 2511surrounded by (cl-block NAME ...).
69d8fb1e
SM
2512
2513\(fn NAME ARGLIST [DOCSTRING] BODY...)"
2ee3d7f0 2514 (declare (debug cl-defun) (indent 2))
4dd1c416 2515 (let* ((argns (cl--arglist-args args)) (p argns)
fcd73769 2516 (pbody (cons 'progn body))
4dd1c416
SM
2517 (unsafe (not (cl--safe-expr-p pbody))))
2518 (while (and p (eq (cl--expr-contains args (car p)) 1)) (pop p))
03fef3e6
SM
2519 `(progn
2520 ,(if p nil ; give up if defaults refer to earlier args
7c1898a7 2521 `(cl-define-compiler-macro ,name
03fef3e6
SM
2522 ,(if (memq '&key args)
2523 `(&whole cl-whole &cl-quote ,@args)
2524 (cons '&cl-quote args))
bb3faf5b 2525 (cl--defsubst-expand
7c1898a7 2526 ',argns '(cl-block ,name ,@body)
03fef3e6
SM
2527 ;; We used to pass `simple' as
2528 ;; (not (or unsafe (cl-expr-access-order pbody argns)))
2529 ;; But this is much too simplistic since it
2530 ;; does not pay attention to the argvs (and
2531 ;; cl-expr-access-order itself is also too naive).
2532 nil
2533 ,(and (memq '&key args) 'cl-whole) ,unsafe ,@argns)))
7c1898a7 2534 (cl-defun ,name ,args ,@body))))
fcd73769 2535
bb3faf5b 2536(defun cl--defsubst-expand (argns body simple whole unsafe &rest argvs)
4dd1c416
SM
2537 (if (and whole (not (cl--safe-expr-p (cons 'progn argvs)))) whole
2538 (if (cl--simple-exprs-p argvs) (setq simple t))
e754e83b
SM
2539 (let* ((substs ())
2540 (lets (delq nil
7c1898a7 2541 (cl-mapcar (lambda (argn argv)
4dd1c416 2542 (if (or simple (macroexp-const-p argv))
7c1898a7
SM
2543 (progn (push (cons argn argv) substs)
2544 (and unsafe (list argn argv)))
2545 (list argn argv)))
2546 argns argvs))))
e754e83b
SM
2547 ;; FIXME: `sublis/subst' will happily substitute the symbol
2548 ;; `argn' in places where it's not used as a reference
2549 ;; to a variable.
2550 ;; FIXME: `sublis/subst' will happily copy `argv' to a different
2551 ;; scope, leading to name capture.
2552 (setq body (cond ((null substs) body)
2553 ((null (cdr substs))
7c1898a7
SM
2554 (cl-subst (cdar substs) (caar substs) body))
2555 (t (cl-sublis substs body))))
03fef3e6 2556 (if lets `(let ,lets ,body) body))))
fcd73769
RS
2557
2558
9b77469a 2559;; Compile-time optimizations for some functions defined in this package.
fcd73769 2560
d9857e53 2561(defun cl--compiler-macro-member (form a list &rest keys)
64a4c526 2562 (let ((test (and (= (length keys) 2) (eq (car keys) :test)
4dd1c416 2563 (cl--const-expr-val (nth 1 keys)))))
03fef3e6
SM
2564 (cond ((eq test 'eq) `(memq ,a ,list))
2565 ((eq test 'equal) `(member ,a ,list))
2566 ((or (null keys) (eq test 'eql)) `(memql ,a ,list))
fcd73769
RS
2567 (t form))))
2568
d9857e53 2569(defun cl--compiler-macro-assoc (form a list &rest keys)
64a4c526 2570 (let ((test (and (= (length keys) 2) (eq (car keys) :test)
4dd1c416 2571 (cl--const-expr-val (nth 1 keys)))))
03fef3e6
SM
2572 (cond ((eq test 'eq) `(assq ,a ,list))
2573 ((eq test 'equal) `(assoc ,a ,list))
4dd1c416
SM
2574 ((and (macroexp-const-p a) (or (null keys) (eq test 'eql)))
2575 (if (cl-floatp-safe (cl--const-expr-val a))
03fef3e6 2576 `(assoc ,a ,list) `(assq ,a ,list)))
fcd73769
RS
2577 (t form))))
2578
71adb94b 2579;;;###autoload
d9857e53 2580(defun cl--compiler-macro-adjoin (form a list &rest keys)
4dd1c416 2581 (if (and (cl--simple-expr-p a) (cl--simple-expr-p list)
64a4c526 2582 (not (memq :key keys)))
7c1898a7 2583 `(if (cl-member ,a ,list ,@keys) ,list (cons ,a ,list))
fcd73769
RS
2584 form))
2585
71adb94b 2586;;;###autoload
d9857e53 2587(defun cl--compiler-macro-list* (_form arg &rest others)
fcd73769
RS
2588 (let* ((args (reverse (cons arg others)))
2589 (form (car args)))
2590 (while (setq args (cdr args))
03fef3e6 2591 (setq form `(cons ,(car args) ,form)))
fcd73769
RS
2592 form))
2593
d9857e53 2594(defun cl--compiler-macro-get (_form sym prop &optional def)
fcd73769 2595 (if def
7c1898a7 2596 `(cl-getf (symbol-plist ,sym) ,prop ,def)
03fef3e6 2597 `(get ,sym ,prop)))
fcd73769 2598
7c1898a7 2599(cl-define-compiler-macro cl-typep (&whole form val type)
4dd1c416 2600 (if (macroexp-const-p type)
2ee3d7f0 2601 (macroexp-let2 macroexp-copyable-p temp val
d9857e53 2602 (cl--make-type-test temp (cl--const-expr-val type)))
fcd73769
RS
2603 form))
2604
71adb94b
SM
2605;;;###autoload
2606(defun cl--compiler-macro-cXXr (form x)
2607 (let* ((head (car form))
2608 (n (symbol-name (car form)))
2609 (i (- (length n) 2)))
2610 (if (not (string-match "c[ad]+r\\'" n))
2611 (if (and (fboundp head) (symbolp (symbol-function head)))
2612 (cl--compiler-macro-cXXr (cons (symbol-function head) (cdr form))
2613 x)
2614 (error "Compiler macro for cXXr applied to non-cXXr form"))
2615 (while (> i (match-beginning 0))
2616 (setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x))
2617 (setq i (1- i)))
2618 x)))
2619
2620(dolist (y '(cl-first cl-second cl-third cl-fourth
2621 cl-fifth cl-sixth cl-seventh
2622 cl-eighth cl-ninth cl-tenth
2623 cl-rest cl-endp cl-plusp cl-minusp
2624 cl-caaar cl-caadr cl-cadar
2625 cl-caddr cl-cdaar cl-cdadr
2626 cl-cddar cl-cdddr cl-caaaar
2627 cl-caaadr cl-caadar cl-caaddr
2628 cl-cadaar cl-cadadr cl-caddar
2629 cl-cadddr cl-cdaaar cl-cdaadr
2630 cl-cdadar cl-cdaddr cl-cddaar
2631 cl-cddadr cl-cdddar cl-cddddr))
2632 (put y 'side-effect-free t))
fcd73769
RS
2633
2634;;; Things that are inline.
2ee3d7f0
SM
2635(cl-proclaim '(inline cl-floatp-safe cl-acons cl-map cl-concatenate cl-notany
2636 cl-notevery cl--set-elt cl-revappend cl-nreconc gethash))
fcd73769
RS
2637
2638;;; Things that are side-effect-free.
e542ea4b 2639(mapc (lambda (x) (put x 'side-effect-free t))
7c1898a7
SM
2640 '(cl-oddp cl-evenp cl-signum last butlast cl-ldiff cl-pairlis cl-gcd cl-lcm
2641 cl-isqrt cl-floor cl-ceiling cl-truncate cl-round cl-mod cl-rem cl-subseq
2642 cl-list-length cl-get cl-getf))
fcd73769
RS
2643
2644;;; Things that are side-effect-and-error-free.
e542ea4b 2645(mapc (lambda (x) (put x 'side-effect-free 'error-free))
7c1898a7
SM
2646 '(eql cl-floatp-safe cl-list* cl-subst cl-acons cl-equalp cl-random-state-p
2647 copy-tree cl-sublis))
fcd73769
RS
2648
2649
2650(run-hooks 'cl-macs-load-hook)
2651
ebacfcc6 2652;; Local variables:
bc8ce89b
GM
2653;; byte-compile-dynamic: t
2654;; byte-compile-warnings: (not cl-functions)
ebacfcc6
SM
2655;; generated-autoload-file: "cl-loaddefs.el"
2656;; End:
b69a3374 2657
de7e2b36
SM
2658(provide 'cl-macs)
2659
fcd73769 2660;;; cl-macs.el ends here