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