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