evaluation time changes
[bpt/emacs.git] / lisp / emacs-lisp / cl-extra.el
CommitLineData
bb3faf5b 1;;; cl-extra.el --- Common Lisp features, part 2 -*- lexical-binding: t -*-
fcd73769 2
ba318903 3;; Copyright (C) 1993, 2000-2014 Free Software Foundation, Inc.
fcd73769
RS
4
5;; Author: Dave Gillespie <daveg@synaptics.com>
fcd73769 6;; Keywords: extensions
bd78fa1d 7;; Package: emacs
fcd73769
RS
8
9;; This file is part of GNU Emacs.
10
d6cba7ae 11;; GNU Emacs is free software: you can redistribute it and/or modify
fcd73769 12;; it under the terms of the GNU General Public License as published by
d6cba7ae
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
fcd73769
RS
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
d6cba7ae 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
fcd73769 23
07b3798c 24;;; Commentary:
fcd73769
RS
25
26;; These are extensions to Emacs Lisp that provide a degree of
27;; Common Lisp compatibility, beyond what is already built-in
28;; in Emacs Lisp.
29;;
30;; This package was written by Dave Gillespie; it is a complete
31;; rewrite of Cesar Quiroz's original cl.el package of December 1986.
32;;
fcd73769
RS
33;; Bug reports, comments, and suggestions are welcome!
34
35;; This file contains portions of the Common Lisp extensions
36;; package which are autoloaded since they are relatively obscure.
37
07b3798c 38;;; Code:
fcd73769 39
7c1898a7 40(require 'cl-lib)
fcd73769 41
fcd73769
RS
42;;; Type coercion.
43
7ed162bc 44;;;###autoload
7c1898a7 45(defun cl-coerce (x type)
fcd73769 46 "Coerce OBJECT to type TYPE.
9ae5b0b9
JB
47TYPE is a Common Lisp type specifier.
48\n(fn OBJECT TYPE)"
fcd73769
RS
49 (cond ((eq type 'list) (if (listp x) x (append x nil)))
50 ((eq type 'vector) (if (vectorp x) x (vconcat x)))
51 ((eq type 'string) (if (stringp x) x (concat x)))
52 ((eq type 'array) (if (arrayp x) x (vconcat x)))
53 ((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0))
338bfefa
SM
54 ((and (eq type 'character) (symbolp x))
55 (cl-coerce (symbol-name x) type))
fcd73769 56 ((eq type 'float) (float x))
7c1898a7 57 ((cl-typep x type) x)
fcd73769
RS
58 (t (error "Can't coerce %s to type %s" x type))))
59
60
61;;; Predicates.
62
7ed162bc 63;;;###autoload
7c1898a7 64(defun cl-equalp (x y)
4ea3cc0e 65 "Return t if two Lisp objects have similar structures and contents.
fcd73769
RS
66This is like `equal', except that it accepts numerically equal
67numbers of different types (float vs. integer), and also compares
68strings case-insensitively."
69 (cond ((eq x y) t)
70 ((stringp x)
71 (and (stringp y) (= (length x) (length y))
76f61009 72 (or (string-equal x y)
338bfefa 73 (string-equal (downcase x) (downcase y))))) ;Lazy but simple!
fcd73769
RS
74 ((numberp x)
75 (and (numberp y) (= x y)))
76 ((consp x)
7c1898a7 77 (while (and (consp x) (consp y) (cl-equalp (car x) (car y)))
e5b633cf 78 (setq x (cdr x) y (cdr y)))
7c1898a7 79 (and (not (consp x)) (cl-equalp x y)))
fcd73769
RS
80 ((vectorp x)
81 (and (vectorp y) (= (length x) (length y))
82 (let ((i (length x)))
83 (while (and (>= (setq i (1- i)) 0)
7c1898a7 84 (cl-equalp (aref x i) (aref y i))))
fcd73769
RS
85 (< i 0))))
86 (t (equal x y))))
87
88
89;;; Control structures.
90
7ed162bc 91;;;###autoload
bb3faf5b 92(defun cl--mapcar-many (cl-func cl-seqs)
fcd73769
RS
93 (if (cdr (cdr cl-seqs))
94 (let* ((cl-res nil)
95 (cl-n (apply 'min (mapcar 'length cl-seqs)))
96 (cl-i 0)
97 (cl-args (copy-sequence cl-seqs))
98 cl-p1 cl-p2)
99 (setq cl-seqs (copy-sequence cl-seqs))
100 (while (< cl-i cl-n)
101 (setq cl-p1 cl-seqs cl-p2 cl-args)
102 (while cl-p1
103 (setcar cl-p2
104 (if (consp (car cl-p1))
105 (prog1 (car (car cl-p1))
106 (setcar cl-p1 (cdr (car cl-p1))))
107 (aref (car cl-p1) cl-i)))
108 (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))
abfb2fe6 109 (push (apply cl-func cl-args) cl-res)
fcd73769
RS
110 (setq cl-i (1+ cl-i)))
111 (nreverse cl-res))
112 (let ((cl-res nil)
113 (cl-x (car cl-seqs))
114 (cl-y (nth 1 cl-seqs)))
115 (let ((cl-n (min (length cl-x) (length cl-y)))
116 (cl-i -1))
117 (while (< (setq cl-i (1+ cl-i)) cl-n)
abfb2fe6 118 (push (funcall cl-func
7c1898a7
SM
119 (if (consp cl-x) (pop cl-x) (aref cl-x cl-i))
120 (if (consp cl-y) (pop cl-y) (aref cl-y cl-i)))
121 cl-res)))
fcd73769
RS
122 (nreverse cl-res))))
123
7ed162bc 124;;;###autoload
7c1898a7 125(defun cl-map (cl-type cl-func cl-seq &rest cl-rest)
9ae5b0b9
JB
126 "Map a FUNCTION across one or more SEQUENCEs, returning a sequence.
127TYPE is the sequence type to return.
128\n(fn TYPE FUNCTION SEQUENCE...)"
7c1898a7
SM
129 (let ((cl-res (apply 'cl-mapcar cl-func cl-seq cl-rest)))
130 (and cl-type (cl-coerce cl-res cl-type))))
fcd73769 131
7ed162bc 132;;;###autoload
7c1898a7 133(defun cl-maplist (cl-func cl-list &rest cl-rest)
9ae5b0b9 134 "Map FUNCTION to each sublist of LIST or LISTs.
5593ed90 135Like `cl-mapcar', except applies to lists and their cdr's rather than to
9ae5b0b9
JB
136the elements themselves.
137\n(fn FUNCTION LIST...)"
fcd73769
RS
138 (if cl-rest
139 (let ((cl-res nil)
140 (cl-args (cons cl-list (copy-sequence cl-rest)))
141 cl-p)
142 (while (not (memq nil cl-args))
abfb2fe6 143 (push (apply cl-func cl-args) cl-res)
fcd73769 144 (setq cl-p cl-args)
abfb2fe6 145 (while cl-p (setcar cl-p (cdr (pop cl-p)) )))
fcd73769
RS
146 (nreverse cl-res))
147 (let ((cl-res nil))
148 (while cl-list
abfb2fe6 149 (push (funcall cl-func cl-list) cl-res)
fcd73769
RS
150 (setq cl-list (cdr cl-list)))
151 (nreverse cl-res))))
152
f43a5263 153;;;###autoload
e10b9e32 154(defun cl-mapc (cl-func cl-seq &rest cl-rest)
f43a5263 155 "Like `cl-mapcar', but does not accumulate values returned by the function.
9ae5b0b9 156\n(fn FUNCTION SEQUENCE...)"
fcd73769 157 (if cl-rest
7c1898a7 158 (progn (apply 'cl-map nil cl-func cl-seq cl-rest)
cf6bc7c3 159 cl-seq)
e2b1c424 160 (mapc cl-func cl-seq)))
fcd73769 161
7ed162bc 162;;;###autoload
7c1898a7
SM
163(defun cl-mapl (cl-func cl-list &rest cl-rest)
164 "Like `cl-maplist', but does not accumulate values returned by the function.
9ae5b0b9 165\n(fn FUNCTION LIST...)"
fcd73769 166 (if cl-rest
7c1898a7 167 (apply 'cl-maplist cl-func cl-list cl-rest)
fcd73769
RS
168 (let ((cl-p cl-list))
169 (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p)))))
170 cl-list)
171
7ed162bc 172;;;###autoload
7c1898a7 173(defun cl-mapcan (cl-func cl-seq &rest cl-rest)
5593ed90 174 "Like `cl-mapcar', but nconc's together the values returned by the function.
9ae5b0b9 175\n(fn FUNCTION SEQUENCE...)"
7c1898a7 176 (apply 'nconc (apply 'cl-mapcar cl-func cl-seq cl-rest)))
fcd73769 177
7ed162bc 178;;;###autoload
7c1898a7
SM
179(defun cl-mapcon (cl-func cl-list &rest cl-rest)
180 "Like `cl-maplist', but nconc's together the values returned by the function.
9ae5b0b9 181\n(fn FUNCTION LIST...)"
7c1898a7 182 (apply 'nconc (apply 'cl-maplist cl-func cl-list cl-rest)))
fcd73769 183
7ed162bc 184;;;###autoload
7c1898a7 185(defun cl-some (cl-pred cl-seq &rest cl-rest)
fcd73769 186 "Return true if PREDICATE is true of any element of SEQ or SEQs.
9ae5b0b9
JB
187If so, return the true (non-nil) value returned by PREDICATE.
188\n(fn PREDICATE SEQ...)"
fcd73769
RS
189 (if (or cl-rest (nlistp cl-seq))
190 (catch 'cl-some
7c1898a7 191 (apply 'cl-map nil
fcd73769
RS
192 (function (lambda (&rest cl-x)
193 (let ((cl-res (apply cl-pred cl-x)))
194 (if cl-res (throw 'cl-some cl-res)))))
195 cl-seq cl-rest) nil)
196 (let ((cl-x nil))
abfb2fe6 197 (while (and cl-seq (not (setq cl-x (funcall cl-pred (pop cl-seq))))))
fcd73769
RS
198 cl-x)))
199
7ed162bc 200;;;###autoload
7c1898a7 201(defun cl-every (cl-pred cl-seq &rest cl-rest)
9ae5b0b9
JB
202 "Return true if PREDICATE is true of every element of SEQ or SEQs.
203\n(fn PREDICATE SEQ...)"
fcd73769
RS
204 (if (or cl-rest (nlistp cl-seq))
205 (catch 'cl-every
7c1898a7 206 (apply 'cl-map nil
fcd73769
RS
207 (function (lambda (&rest cl-x)
208 (or (apply cl-pred cl-x) (throw 'cl-every nil))))
209 cl-seq cl-rest) t)
210 (while (and cl-seq (funcall cl-pred (car cl-seq)))
211 (setq cl-seq (cdr cl-seq)))
212 (null cl-seq)))
213
7ed162bc 214;;;###autoload
7c1898a7 215(defun cl-notany (cl-pred cl-seq &rest cl-rest)
9ae5b0b9
JB
216 "Return true if PREDICATE is false of every element of SEQ or SEQs.
217\n(fn PREDICATE SEQ...)"
7c1898a7 218 (not (apply 'cl-some cl-pred cl-seq cl-rest)))
fcd73769 219
7ed162bc 220;;;###autoload
7c1898a7 221(defun cl-notevery (cl-pred cl-seq &rest cl-rest)
9ae5b0b9
JB
222 "Return true if PREDICATE is false of some element of SEQ or SEQs.
223\n(fn PREDICATE SEQ...)"
7c1898a7 224 (not (apply 'cl-every cl-pred cl-seq cl-rest)))
fcd73769 225
7ed162bc 226;;;###autoload
bb3faf5b 227(defun cl--map-keymap-recursively (cl-func-rec cl-map &optional cl-base)
fcd73769 228 (or cl-base
61255981 229 (setq cl-base (copy-sequence [0])))
09dae035 230 (map-keymap
fcd73769
RS
231 (function
232 (lambda (cl-key cl-bind)
233 (aset cl-base (1- (length cl-base)) cl-key)
234 (if (keymapp cl-bind)
bb3faf5b 235 (cl--map-keymap-recursively
fcd73769 236 cl-func-rec cl-bind
61255981 237 (vconcat cl-base (list 0)))
fcd73769
RS
238 (funcall cl-func-rec cl-base cl-bind))))
239 cl-map))
240
7ed162bc 241;;;###autoload
bb3faf5b 242(defun cl--map-intervals (cl-func &optional cl-what cl-prop cl-start cl-end)
fcd73769
RS
243 (or cl-what (setq cl-what (current-buffer)))
244 (if (bufferp cl-what)
245 (let (cl-mark cl-mark2 (cl-next t) cl-next2)
cf6bc7c3 246 (with-current-buffer cl-what
fcd73769
RS
247 (setq cl-mark (copy-marker (or cl-start (point-min))))
248 (setq cl-mark2 (and cl-end (copy-marker cl-end))))
249 (while (and cl-next (or (not cl-mark2) (< cl-mark cl-mark2)))
cf6bc7c3
DL
250 (setq cl-next (if cl-prop (next-single-property-change
251 cl-mark cl-prop cl-what)
252 (next-property-change cl-mark cl-what))
253 cl-next2 (or cl-next (with-current-buffer cl-what
254 (point-max))))
fcd73769
RS
255 (funcall cl-func (prog1 (marker-position cl-mark)
256 (set-marker cl-mark cl-next2))
257 (if cl-mark2 (min cl-next2 cl-mark2) cl-next2)))
258 (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil)))
259 (or cl-start (setq cl-start 0))
260 (or cl-end (setq cl-end (length cl-what)))
261 (while (< cl-start cl-end)
cf6bc7c3
DL
262 (let ((cl-next (or (if cl-prop (next-single-property-change
263 cl-start cl-prop cl-what)
264 (next-property-change cl-start cl-what))
fcd73769
RS
265 cl-end)))
266 (funcall cl-func cl-start (min cl-next cl-end))
267 (setq cl-start cl-next)))))
268
7ed162bc 269;;;###autoload
bb3faf5b 270(defun cl--map-overlays (cl-func &optional cl-buffer cl-start cl-end cl-arg)
fcd73769 271 (or cl-buffer (setq cl-buffer (current-buffer)))
814e26fa
JB
272 (let (cl-ovl)
273 (with-current-buffer cl-buffer
274 (setq cl-ovl (overlay-lists))
275 (if cl-start (setq cl-start (copy-marker cl-start)))
276 (if cl-end (setq cl-end (copy-marker cl-end))))
277 (setq cl-ovl (nconc (car cl-ovl) (cdr cl-ovl)))
278 (while (and cl-ovl
279 (or (not (overlay-start (car cl-ovl)))
280 (and cl-end (>= (overlay-start (car cl-ovl)) cl-end))
281 (and cl-start (<= (overlay-end (car cl-ovl)) cl-start))
282 (not (funcall cl-func (car cl-ovl) cl-arg))))
283 (setq cl-ovl (cdr cl-ovl)))
284 (if cl-start (set-marker cl-start nil))
285 (if cl-end (set-marker cl-end nil))))
fcd73769 286
2ee3d7f0 287;;; Support for `setf'.
7ed162bc 288;;;###autoload
bb3faf5b 289(defun cl--set-frame-visible-p (frame val)
fcd73769
RS
290 (cond ((null val) (make-frame-invisible frame))
291 ((eq val 'icon) (iconify-frame frame))
292 (t (make-frame-visible frame)))
293 val)
294
fcd73769
RS
295
296;;; Numbers.
297
7ed162bc 298;;;###autoload
7c1898a7 299(defun cl-gcd (&rest args)
fcd73769 300 "Return the greatest common divisor of the arguments."
abfb2fe6 301 (let ((a (abs (or (pop args) 0))))
fcd73769 302 (while args
abfb2fe6 303 (let ((b (abs (pop args))))
fcd73769
RS
304 (while (> b 0) (setq b (% a (setq a b))))))
305 a))
306
7ed162bc 307;;;###autoload
7c1898a7 308(defun cl-lcm (&rest args)
fcd73769
RS
309 "Return the least common multiple of the arguments."
310 (if (memq 0 args)
311 0
abfb2fe6 312 (let ((a (abs (or (pop args) 1))))
fcd73769 313 (while args
abfb2fe6 314 (let ((b (abs (pop args))))
7c1898a7 315 (setq a (* (/ a (cl-gcd a b)) b))))
fcd73769
RS
316 a)))
317
7ed162bc 318;;;###autoload
7c1898a7 319(defun cl-isqrt (x)
fcd73769 320 "Return the integer square root of the argument."
9ae5b0b9
JB
321 (if (and (integerp x) (> x 0))
322 (let ((g (cond ((<= x 100) 10) ((<= x 10000) 100)
323 ((<= x 1000000) 1000) (t x)))
fcd73769 324 g2)
9ae5b0b9 325 (while (< (setq g2 (/ (+ g (/ x g)) 2)) g)
fcd73769
RS
326 (setq g g2))
327 g)
9ae5b0b9 328 (if (eq x 0) 0 (signal 'arith-error nil))))
fcd73769 329
7ed162bc 330;;;###autoload
7c1898a7 331(defun cl-floor (x &optional y)
fcd73769
RS
332 "Return a list of the floor of X and the fractional part of X.
333With two arguments, return floor and remainder of their quotient."
ebe6b814
PE
334 (let ((q (floor x y)))
335 (list q (- x (if y (* y q) q)))))
fcd73769 336
7ed162bc 337;;;###autoload
7c1898a7 338(defun cl-ceiling (x &optional y)
fcd73769
RS
339 "Return a list of the ceiling of X and the fractional part of X.
340With two arguments, return ceiling and remainder of their quotient."
7c1898a7 341 (let ((res (cl-floor x y)))
fcd73769
RS
342 (if (= (car (cdr res)) 0) res
343 (list (1+ (car res)) (- (car (cdr res)) (or y 1))))))
344
7ed162bc 345;;;###autoload
7c1898a7 346(defun cl-truncate (x &optional y)
fcd73769
RS
347 "Return a list of the integer part of X and the fractional part of X.
348With two arguments, return truncation and remainder of their quotient."
349 (if (eq (>= x 0) (or (null y) (>= y 0)))
7c1898a7 350 (cl-floor x y) (cl-ceiling x y)))
fcd73769 351
7ed162bc 352;;;###autoload
7c1898a7 353(defun cl-round (x &optional y)
fcd73769
RS
354 "Return a list of X rounded to the nearest integer and the remainder.
355With two arguments, return rounding and remainder of their quotient."
356 (if y
357 (if (and (integerp x) (integerp y))
358 (let* ((hy (/ y 2))
7c1898a7 359 (res (cl-floor (+ x hy) y)))
fcd73769
RS
360 (if (and (= (car (cdr res)) 0)
361 (= (+ hy hy) y)
362 (/= (% (car res) 2) 0))
363 (list (1- (car res)) hy)
364 (list (car res) (- (car (cdr res)) hy))))
365 (let ((q (round (/ x y))))
366 (list q (- x (* q y)))))
367 (if (integerp x) (list x 0)
368 (let ((q (round x)))
369 (list q (- x q))))))
370
7ed162bc 371;;;###autoload
7c1898a7 372(defun cl-mod (x y)
fcd73769 373 "The remainder of X divided by Y, with the same sign as Y."
7c1898a7 374 (nth 1 (cl-floor x y)))
fcd73769 375
7ed162bc 376;;;###autoload
7c1898a7 377(defun cl-rem (x y)
fcd73769 378 "The remainder of X divided by Y, with the same sign as X."
7c1898a7 379 (nth 1 (cl-truncate x y)))
fcd73769 380
7ed162bc 381;;;###autoload
7c1898a7 382(defun cl-signum (x)
9ae5b0b9
JB
383 "Return 1 if X is positive, -1 if negative, 0 if zero."
384 (cond ((> x 0) 1) ((< x 0) -1) (t 0)))
fcd73769
RS
385
386
387;; Random numbers.
388
7ed162bc 389;;;###autoload
7c1898a7 390(defun cl-random (lim &optional state)
fcd73769
RS
391 "Return a random nonnegative number less than LIM, an integer or float.
392Optional second arg STATE is a random-state object."
4735906a 393 (or state (setq state cl--random-state))
fcd73769
RS
394 ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method.
395 (let ((vec (aref state 3)))
396 (if (integerp vec)
7ed162bc 397 (let ((i 0) (j (- 1357335 (% (abs vec) 1357333))) (k 1))
fcd73769
RS
398 (aset state 3 (setq vec (make-vector 55 nil)))
399 (aset vec 0 j)
400 (while (> (setq i (% (+ i 21) 55)) 0)
401 (aset vec i (setq j (prog1 k (setq k (- j k))))))
7c1898a7 402 (while (< (setq i (1+ i)) 200) (cl-random 2 state))))
fcd73769
RS
403 (let* ((i (aset state 1 (% (1+ (aref state 1)) 55)))
404 (j (aset state 2 (% (1+ (aref state 2)) 55)))
405 (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j))))))
406 (if (integerp lim)
407 (if (<= lim 512) (% n lim)
7c1898a7 408 (if (> lim 8388607) (setq n (+ (lsh n 9) (cl-random 512 state))))
fcd73769
RS
409 (let ((mask 1023))
410 (while (< mask (1- lim)) (setq mask (1+ (+ mask mask))))
7c1898a7 411 (if (< (setq n (logand n mask)) lim) n (cl-random lim state))))
fcd73769
RS
412 (* (/ n '8388608e0) lim)))))
413
7ed162bc 414;;;###autoload
7c1898a7 415(defun cl-make-random-state (&optional state)
4735906a 416 "Return a copy of random-state STATE, or of the internal state if omitted.
fcd73769 417If STATE is t, return a new state object seeded from the time of day."
7c1898a7 418 (cond ((null state) (cl-make-random-state cl--random-state))
6fa6c4ae 419 ((vectorp state) (copy-tree state t))
338bfefa 420 ((integerp state) (vector 'cl--random-state-tag -1 30 state))
376a8e83 421 (t (cl-make-random-state (cl--random-time)))))
fcd73769 422
7ed162bc 423;;;###autoload
7c1898a7 424(defun cl-random-state-p (object)
fcd73769
RS
425 "Return t if OBJECT is a random-state object."
426 (and (vectorp object) (= (length object) 4)
338bfefa 427 (eq (aref object 0) 'cl--random-state-tag)))
fcd73769
RS
428
429
430;; Implementation limits.
431
bb3faf5b
SM
432(defun cl--finite-do (func a b)
433 (condition-case _
fcd73769
RS
434 (let ((res (funcall func a b))) ; check for IEEE infinity
435 (and (numberp res) (/= res (/ res 2)) res))
436 (arith-error nil)))
437
7ed162bc 438;;;###autoload
fcd73769 439(defun cl-float-limits ()
416a2c45 440 "Initialize the Common Lisp floating-point parameters.
7c1898a7
SM
441This sets the values of: `cl-most-positive-float', `cl-most-negative-float',
442`cl-least-positive-float', `cl-least-negative-float', `cl-float-epsilon',
443`cl-float-negative-epsilon', `cl-least-positive-normalized-float', and
444`cl-least-negative-normalized-float'."
445 (or cl-most-positive-float (not (numberp '2e1))
fcd73769
RS
446 (let ((x '2e0) y z)
447 ;; Find maximum exponent (first two loops are optimizations)
bb3faf5b
SM
448 (while (cl--finite-do '* x x) (setq x (* x x)))
449 (while (cl--finite-do '* x (/ x 2)) (setq x (* x (/ x 2))))
450 (while (cl--finite-do '+ x x) (setq x (+ x x)))
fcd73769 451 (setq z x y (/ x 2))
7c1898a7 452 ;; Now cl-fill in 1's in the mantissa.
bb3faf5b 453 (while (and (cl--finite-do '+ x y) (/= (+ x y) x))
fcd73769 454 (setq x (+ x y) y (/ y 2)))
7c1898a7
SM
455 (setq cl-most-positive-float x
456 cl-most-negative-float (- x))
fcd73769
RS
457 ;; Divide down until mantissa starts rounding.
458 (setq x (/ x z) y (/ 16 z) x (* x y))
bb3faf5b 459 (while (condition-case _ (and (= x (* (/ x 2) 2)) (> (/ y 2) 0))
fcd73769
RS
460 (arith-error nil))
461 (setq x (/ x 2) y (/ y 2)))
7c1898a7
SM
462 (setq cl-least-positive-normalized-float y
463 cl-least-negative-normalized-float (- y))
fcd73769
RS
464 ;; Divide down until value underflows to zero.
465 (setq x (/ 1 z) y x)
bb3faf5b 466 (while (condition-case _ (> (/ x 2) 0) (arith-error nil))
fcd73769 467 (setq x (/ x 2)))
7c1898a7
SM
468 (setq cl-least-positive-float x
469 cl-least-negative-float (- x))
fcd73769
RS
470 (setq x '1e0)
471 (while (/= (+ '1e0 x) '1e0) (setq x (/ x 2)))
7c1898a7 472 (setq cl-float-epsilon (* x 2))
fcd73769
RS
473 (setq x '1e0)
474 (while (/= (- '1e0 x) '1e0) (setq x (/ x 2)))
7c1898a7 475 (setq cl-float-negative-epsilon (* x 2))))
fcd73769
RS
476 nil)
477
478
479;;; Sequence functions.
480
7ed162bc 481;;;###autoload
7c1898a7 482(defun cl-subseq (seq start &optional end)
fcd73769
RS
483 "Return the subsequence of SEQ from START to END.
484If END is omitted, it defaults to the length of the sequence.
485If START or END is negative, it counts from the end."
36cec983
SM
486 (declare (gv-setter
487 (lambda (new)
488 `(progn (cl-replace ,seq ,new :start1 ,start :end1 ,end)
489 ,new))))
fcd73769
RS
490 (if (stringp seq) (substring seq start end)
491 (let (len)
492 (and end (< end 0) (setq end (+ end (setq len (length seq)))))
493 (if (< start 0) (setq start (+ start (or len (setq len (length seq))))))
494 (cond ((listp seq)
495 (if (> start 0) (setq seq (nthcdr start seq)))
496 (if end
497 (let ((res nil))
498 (while (>= (setq end (1- end)) start)
abfb2fe6 499 (push (pop seq) res))
fcd73769
RS
500 (nreverse res))
501 (copy-sequence seq)))
502 (t
503 (or end (setq end (or len (length seq))))
504 (let ((res (make-vector (max (- end start) 0) nil))
505 (i 0))
506 (while (< start end)
507 (aset res i (aref seq start))
508 (setq i (1+ i) start (1+ start)))
509 res))))))
510
7ed162bc 511;;;###autoload
7c1898a7 512(defun cl-concatenate (type &rest seqs)
9ae5b0b9
JB
513 "Concatenate, into a sequence of type TYPE, the argument SEQUENCEs.
514\n(fn TYPE SEQUENCE...)"
fcd73769
RS
515 (cond ((eq type 'vector) (apply 'vconcat seqs))
516 ((eq type 'string) (apply 'concat seqs))
517 ((eq type 'list) (apply 'append (append seqs '(nil))))
518 (t (error "Not a sequence type name: %s" type))))
519
520
521;;; List functions.
522
7ed162bc 523;;;###autoload
7c1898a7 524(defun cl-revappend (x y)
fcd73769
RS
525 "Equivalent to (append (reverse X) Y)."
526 (nconc (reverse x) y))
527
7ed162bc 528;;;###autoload
7c1898a7 529(defun cl-nreconc (x y)
fcd73769
RS
530 "Equivalent to (nconc (nreverse X) Y)."
531 (nconc (nreverse x) y))
532
7ed162bc 533;;;###autoload
7c1898a7 534(defun cl-list-length (x)
9ae5b0b9 535 "Return the length of list X. Return nil if list is circular."
fcd73769
RS
536 (let ((n 0) (fast x) (slow x))
537 (while (and (cdr fast) (not (and (eq fast slow) (> n 0))))
538 (setq n (+ n 2) fast (cdr (cdr fast)) slow (cdr slow)))
539 (if fast (if (cdr fast) nil (1+ n)) n)))
540
7ed162bc 541;;;###autoload
7c1898a7 542(defun cl-tailp (sublist list)
fcd73769
RS
543 "Return true if SUBLIST is a tail of LIST."
544 (while (and (consp list) (not (eq sublist list)))
545 (setq list (cdr list)))
546 (if (numberp sublist) (equal sublist list) (eq sublist list)))
547
fcd73769
RS
548;;; Property lists.
549
7ed162bc 550;;;###autoload
d9857e53 551(defun cl-get (sym tag &optional def)
9ae5b0b9
JB
552 "Return the value of SYMBOL's PROPNAME property, or DEFAULT if none.
553\n(fn SYMBOL PROPNAME &optional DEFAULT)"
36cec983
SM
554 (declare (compiler-macro cl--compiler-macro-get)
555 (gv-setter (lambda (store) `(put ,sym ,tag ,store))))
fcd73769
RS
556 (or (get sym tag)
557 (and def
2ee3d7f0 558 ;; Make sure `def' is really absent as opposed to set to nil.
fcd73769
RS
559 (let ((plist (symbol-plist sym)))
560 (while (and plist (not (eq (car plist) tag)))
561 (setq plist (cdr (cdr plist))))
562 (if plist (car (cdr plist)) def)))))
d9857e53 563(autoload 'cl--compiler-macro-get "cl-macs")
fcd73769 564
7ed162bc 565;;;###autoload
7c1898a7 566(defun cl-getf (plist tag &optional def)
fcd73769 567 "Search PROPLIST for property PROPNAME; return its value or DEFAULT.
9ae5b0b9
JB
568PROPLIST is a list of the sort returned by `symbol-plist'.
569\n(fn PROPLIST PROPNAME &optional DEFAULT)"
36cec983
SM
570 (declare (gv-expander
571 (lambda (do)
572 (gv-letplace (getter setter) plist
573 (macroexp-let2 nil k tag
574 (macroexp-let2 nil d def
575 (funcall do `(cl-getf ,getter ,k ,d)
576 (lambda (v)
c46c57b0
SM
577 (macroexp-let2 nil val v
578 `(progn
579 ,(funcall setter
580 `(cl--set-getf ,getter ,k ,val))
581 ,val))))))))))
fcd73769
RS
582 (setplist '--cl-getf-symbol-- plist)
583 (or (get '--cl-getf-symbol-- tag)
7c1898a7
SM
584 ;; Originally we called cl-get here,
585 ;; but that fails, because cl-get has a compiler macro
318f417c
KH
586 ;; definition that uses getf!
587 (when def
2ee3d7f0 588 ;; Make sure `def' is really absent as opposed to set to nil.
318f417c
KH
589 (while (and plist (not (eq (car plist) tag)))
590 (setq plist (cdr (cdr plist))))
591 (if plist (car (cdr plist)) def))))
fcd73769 592
7ed162bc 593;;;###autoload
bb3faf5b 594(defun cl--set-getf (plist tag val)
fcd73769
RS
595 (let ((p plist))
596 (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p))))
7c1898a7 597 (if p (progn (setcar (cdr p) val) plist) (cl-list* tag val plist))))
fcd73769 598
7ed162bc 599;;;###autoload
bb3faf5b 600(defun cl--do-remf (plist tag)
fcd73769
RS
601 (let ((p (cdr plist)))
602 (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p))))
603 (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t))))
604
7ed162bc 605;;;###autoload
fcd73769 606(defun cl-remprop (sym tag)
9ae5b0b9
JB
607 "Remove from SYMBOL's plist the property PROPNAME and its value.
608\n(fn SYMBOL PROPNAME)"
fcd73769
RS
609 (let ((plist (symbol-plist sym)))
610 (if (and plist (eq tag (car plist)))
611 (progn (setplist sym (cdr (cdr plist))) t)
bb3faf5b 612 (cl--do-remf plist tag))))
fcd73769 613
fcd73769
RS
614;;; Some debugging aids.
615
616(defun cl-prettyprint (form)
617 "Insert a pretty-printed rendition of a Lisp FORM in current buffer."
618 (let ((pt (point)) last)
619 (insert "\n" (prin1-to-string form) "\n")
620 (setq last (point))
621 (goto-char (1+ pt))
622 (while (search-forward "(quote " last t)
d355a0b7 623 (delete-char -7)
fcd73769
RS
624 (insert "'")
625 (forward-sexp)
626 (delete-char 1))
627 (goto-char (1+ pt))
bb3faf5b 628 (cl--do-prettyprint)))
fcd73769 629
bb3faf5b 630(defun cl--do-prettyprint ()
fcd73769
RS
631 (skip-chars-forward " ")
632 (if (looking-at "(")
633 (let ((skip (or (looking-at "((") (looking-at "(prog")
634 (looking-at "(unwind-protect ")
635 (looking-at "(function (")
bb3faf5b 636 (looking-at "(cl--block-wrapper ")))
fcd73769
RS
637 (two (or (looking-at "(defun ") (looking-at "(defmacro ")))
638 (let (or (looking-at "(let\\*? ") (looking-at "(while ")))
639 (set (looking-at "(p?set[qf] ")))
640 (if (or skip let
641 (progn
642 (forward-sexp)
643 (and (>= (current-column) 78) (progn (backward-sexp) t))))
644 (let ((nl t))
645 (forward-char 1)
bb3faf5b
SM
646 (cl--do-prettyprint)
647 (or skip (looking-at ")") (cl--do-prettyprint))
648 (or (not two) (looking-at ")") (cl--do-prettyprint))
fcd73769
RS
649 (while (not (looking-at ")"))
650 (if set (setq nl (not nl)))
651 (if nl (insert "\n"))
652 (lisp-indent-line)
bb3faf5b 653 (cl--do-prettyprint))
fcd73769
RS
654 (forward-char 1))))
655 (forward-sexp)))
656
7ed162bc 657;;;###autoload
fcd73769 658(defun cl-prettyexpand (form &optional full)
5593ed90
GM
659 "Expand macros in FORM and insert the pretty-printed result.
660Optional argument FULL non-nil means to expand all macros,
661including `cl-block' and `cl-eval-when'."
fcd73769 662 (message "Expanding...")
bb3faf5b 663 (let ((cl--compiling-file full)
fcd73769 664 (byte-compile-macro-environment nil))
6fa6c4ae
SM
665 (setq form (macroexpand-all form
666 (and (not full) '((cl-block) (cl-eval-when)))))
fcd73769
RS
667 (message "Formatting...")
668 (prog1 (cl-prettyprint form)
669 (message ""))))
670
671
672
673(run-hooks 'cl-extra-load-hook)
674
7ed162bc 675;; Local variables:
91677576 676;; byte-compile-dynamic: t
7ed162bc
SM
677;; generated-autoload-file: "cl-loaddefs.el"
678;; End:
679
fcd73769 680;;; cl-extra.el ends here