diff options
| author | Richard M. Stallman | 1993-07-30 20:15:09 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-07-30 20:15:09 +0000 |
| commit | fcd737693e8e320acd70f91ec8e0728563244805 (patch) | |
| tree | 23dee4ef9fea51d370e346e80d765f2a81a29404 | |
| parent | 9b973fd79bcbb6753d1495d49c58a6a1c0eac304 (diff) | |
| download | emacs-fcd737693e8e320acd70f91ec8e0728563244805.tar.gz emacs-fcd737693e8e320acd70f91ec8e0728563244805.zip | |
entered into RCS
| -rw-r--r-- | lisp/emacs-lisp/cl-compat.el | 191 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-extra.el | 930 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 2610 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-seq.el | 920 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl.el | 757 |
5 files changed, 5408 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/cl-compat.el b/lisp/emacs-lisp/cl-compat.el new file mode 100644 index 00000000000..f02f6f4db2b --- /dev/null +++ b/lisp/emacs-lisp/cl-compat.el | |||
| @@ -0,0 +1,191 @@ | |||
| 1 | ;; cl-compat.el --- Common Lisp extensions for GNU Emacs Lisp (compatibility) | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Dave Gillespie <daveg@synaptics.com> | ||
| 6 | ;; Version: 2.02 | ||
| 7 | ;; Keywords: extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 14 | ;; any later version. | ||
| 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 | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | ;; Commentary: | ||
| 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 | ;; | ||
| 34 | ;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. | ||
| 35 | ;; | ||
| 36 | ;; Bug reports, comments, and suggestions are welcome! | ||
| 37 | |||
| 38 | ;; This file contains emulations of internal routines of the older | ||
| 39 | ;; CL package which users may have called directly from their code. | ||
| 40 | ;; Use (require 'cl-compat) to get these routines. | ||
| 41 | |||
| 42 | ;; See cl.el for Change Log. | ||
| 43 | |||
| 44 | |||
| 45 | ;; Code: | ||
| 46 | |||
| 47 | ;; Require at load-time, but not when compiling cl-compat. | ||
| 48 | (or (featurep 'cl) (require 'cl)) | ||
| 49 | |||
| 50 | |||
| 51 | ;;; Keyword routines not supported by new package. | ||
| 52 | |||
| 53 | (defmacro defkeyword (x &optional doc) | ||
| 54 | (list* 'defconst x (list 'quote x) (and doc (list doc)))) | ||
| 55 | |||
| 56 | (defun keywordp (sym) | ||
| 57 | (and (symbolp sym) (eq (aref (symbol-name sym) 0) ?\:) (set sym sym))) | ||
| 58 | |||
| 59 | (defun keyword-of (sym) | ||
| 60 | (or (keywordp sym) (keywordp (intern (format ":%s" sym))))) | ||
| 61 | |||
| 62 | |||
| 63 | ;;; Multiple values. Note that the new package uses a different | ||
| 64 | ;;; convention for multiple values. The following definitions | ||
| 65 | ;;; emulate the old convention; all function names have been changed | ||
| 66 | ;;; by capitalizing the first letter: Values, Multiple-value-*, | ||
| 67 | ;;; to avoid conflict with the new-style definitions in cl-macs. | ||
| 68 | |||
| 69 | (put 'Multiple-value-bind 'lisp-indent-function 2) | ||
| 70 | (put 'Multiple-value-setq 'lisp-indent-function 2) | ||
| 71 | (put 'Multiple-value-call 'lisp-indent-function 1) | ||
| 72 | (put 'Multiple-value-prog1 'lisp-indent-function 1) | ||
| 73 | |||
| 74 | (defvar *mvalues-values* nil) | ||
| 75 | |||
| 76 | (defun Values (&rest val-forms) | ||
| 77 | (setq *mvalues-values* val-forms) | ||
| 78 | (car val-forms)) | ||
| 79 | |||
| 80 | (defun Values-list (val-forms) | ||
| 81 | (apply 'values val-forms)) | ||
| 82 | |||
| 83 | (defmacro Multiple-value-list (form) | ||
| 84 | (list 'let* (list '(*mvalues-values* nil) (list '*mvalues-temp* form)) | ||
| 85 | '(or (and (eq *mvalues-temp* (car *mvalues-values*)) *mvalues-values*) | ||
| 86 | (list *mvalues-temp*)))) | ||
| 87 | |||
| 88 | (defmacro Multiple-value-call (function &rest args) | ||
| 89 | (list 'apply function | ||
| 90 | (cons 'append | ||
| 91 | (mapcar (function (lambda (x) (list 'Multiple-value-list x))) | ||
| 92 | args)))) | ||
| 93 | |||
| 94 | (defmacro Multiple-value-bind (vars form &rest body) | ||
| 95 | (list* 'multiple-value-bind vars (list 'Multiple-value-list form) body)) | ||
| 96 | |||
| 97 | (defmacro Multiple-value-setq (vars form) | ||
| 98 | (list 'multiple-value-setq vars (list 'Multiple-value-list form))) | ||
| 99 | |||
| 100 | (defmacro Multiple-value-prog1 (form &rest body) | ||
| 101 | (list 'prog1 form (list* 'let '((*mvalues-values* nil)) body))) | ||
| 102 | |||
| 103 | |||
| 104 | ;;; Routines for parsing keyword arguments. | ||
| 105 | |||
| 106 | (defun build-klist (arglist keys &optional allow-others) | ||
| 107 | (let ((res (Multiple-value-call 'mapcar* 'cons (unzip-lists arglist)))) | ||
| 108 | (or allow-others | ||
| 109 | (let ((bad (set-difference (mapcar 'car res) keys))) | ||
| 110 | (if bad (error "Bad keywords: %s not in %s" bad keys)))) | ||
| 111 | res)) | ||
| 112 | |||
| 113 | (defun extract-from-klist (klist key &optional def) | ||
| 114 | (let ((res (assq key klist))) (if res (cdr res) def))) | ||
| 115 | |||
| 116 | (defun keyword-argument-supplied-p (klist key) | ||
| 117 | (assq key klist)) | ||
| 118 | |||
| 119 | (defun elt-satisfies-test-p (item elt klist) | ||
| 120 | (let ((test-not (cdr (assq ':test-not klist))) | ||
| 121 | (test (cdr (assq ':test klist))) | ||
| 122 | (key (cdr (assq ':key klist)))) | ||
| 123 | (if key (setq elt (funcall key elt))) | ||
| 124 | (if test-not (not (funcall test-not item elt)) | ||
| 125 | (funcall (or test 'eql) item elt)))) | ||
| 126 | |||
| 127 | |||
| 128 | ;;; Rounding functions with old-style multiple value returns. | ||
| 129 | |||
| 130 | (defun cl-floor (a &optional b) (Values-list (floor* a b))) | ||
| 131 | (defun cl-ceiling (a &optional b) (Values-list (ceiling* a b))) | ||
| 132 | (defun cl-round (a &optional b) (Values-list (round* a b))) | ||
| 133 | (defun cl-truncate (a &optional b) (Values-list (truncate* a b))) | ||
| 134 | |||
| 135 | (defun safe-idiv (a b) | ||
| 136 | (let* ((q (/ (abs a) (abs b))) | ||
| 137 | (s (* (signum a) (signum b)))) | ||
| 138 | (Values q (- a (* s q b)) s))) | ||
| 139 | |||
| 140 | |||
| 141 | ;; Internal routines. | ||
| 142 | |||
| 143 | (defun pair-with-newsyms (oldforms) | ||
| 144 | (let ((newsyms (mapcar (function (lambda (x) (gensym))) oldforms))) | ||
| 145 | (Values (mapcar* 'list newsyms oldforms) newsyms))) | ||
| 146 | |||
| 147 | (defun zip-lists (evens odds) | ||
| 148 | (mapcan 'list evens odds)) | ||
| 149 | |||
| 150 | (defun unzip-lists (list) | ||
| 151 | (let ((e nil) (o nil)) | ||
| 152 | (while list | ||
| 153 | (setq e (cons (car list) e) o (cons (cadr list) o) list (cddr list))) | ||
| 154 | (Values (nreverse e) (nreverse o)))) | ||
| 155 | |||
| 156 | (defun reassemble-argslists (list) | ||
| 157 | (let ((n (apply 'min (mapcar 'length list))) (res nil)) | ||
| 158 | (while (>= (setq n (1- n)) 0) | ||
| 159 | (setq res (cons (mapcar (function (lambda (x) (elt x n))) list) res))) | ||
| 160 | res)) | ||
| 161 | |||
| 162 | (defun duplicate-symbols-p (list) | ||
| 163 | (let ((res nil)) | ||
| 164 | (while list | ||
| 165 | (if (memq (car list) (cdr list)) (setq res (cons (car list) res))) | ||
| 166 | (setq list (cdr list))) | ||
| 167 | res)) | ||
| 168 | |||
| 169 | |||
| 170 | ;;; Setf internals. | ||
| 171 | |||
| 172 | (defun setnth (n list x) | ||
| 173 | (setcar (nthcdr n list) x)) | ||
| 174 | |||
| 175 | (defun setnthcdr (n list x) | ||
| 176 | (setcdr (nthcdr (1- n) list) x)) | ||
| 177 | |||
| 178 | (defun setelt (seq n x) | ||
| 179 | (if (consp seq) (setcar (nthcdr n seq) x) (aset seq n x))) | ||
| 180 | |||
| 181 | |||
| 182 | ;;; Functions omitted: case-clausify, check-do-stepforms, check-do-endforms, | ||
| 183 | ;;; extract-do-inits, extract-do[*]-steps, select-stepping-forms, | ||
| 184 | ;;; elt-satisfies-if[-not]-p, with-keyword-args, mv-bind-clausify, | ||
| 185 | ;;; all names with embedded `$'. | ||
| 186 | |||
| 187 | |||
| 188 | (provide 'cl-compat) | ||
| 189 | |||
| 190 | ;;; cl-compat.el ends here | ||
| 191 | |||
diff --git a/lisp/emacs-lisp/cl-extra.el b/lisp/emacs-lisp/cl-extra.el new file mode 100644 index 00000000000..5b1fcc49b3d --- /dev/null +++ b/lisp/emacs-lisp/cl-extra.el | |||
| @@ -0,0 +1,930 @@ | |||
| 1 | ;; cl-extra.el --- Common Lisp extensions for GNU Emacs Lisp (part two) | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Dave Gillespie <daveg@synaptics.com> | ||
| 6 | ;; Version: 2.02 | ||
| 7 | ;; Keywords: extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 14 | ;; any later version. | ||
| 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 | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | ;; Commentary: | ||
| 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 | ;; | ||
| 34 | ;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. | ||
| 35 | ;; | ||
| 36 | ;; Bug reports, comments, and suggestions are welcome! | ||
| 37 | |||
| 38 | ;; This file contains portions of the Common Lisp extensions | ||
| 39 | ;; package which are autoloaded since they are relatively obscure. | ||
| 40 | |||
| 41 | ;; See cl.el for Change Log. | ||
| 42 | |||
| 43 | |||
| 44 | ;; Code: | ||
| 45 | |||
| 46 | (or (memq 'cl-19 features) | ||
| 47 | (error "Tried to load `cl-extra' before `cl'!")) | ||
| 48 | |||
| 49 | |||
| 50 | ;;; We define these here so that this file can compile without having | ||
| 51 | ;;; loaded the cl.el file already. | ||
| 52 | |||
| 53 | (defmacro cl-push (x place) (list 'setq place (list 'cons x place))) | ||
| 54 | (defmacro cl-pop (place) | ||
| 55 | (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) | ||
| 56 | |||
| 57 | (defvar cl-emacs-type) | ||
| 58 | |||
| 59 | |||
| 60 | ;;; Type coercion. | ||
| 61 | |||
| 62 | (defun coerce (x type) | ||
| 63 | "Coerce OBJECT to type TYPE. | ||
| 64 | TYPE is a Common Lisp type specifier." | ||
| 65 | (cond ((eq type 'list) (if (listp x) x (append x nil))) | ||
| 66 | ((eq type 'vector) (if (vectorp x) x (vconcat x))) | ||
| 67 | ((eq type 'string) (if (stringp x) x (concat x))) | ||
| 68 | ((eq type 'array) (if (arrayp x) x (vconcat x))) | ||
| 69 | ((and (eq type 'character) (stringp x) (= (length x) 1)) (aref x 0)) | ||
| 70 | ((and (eq type 'character) (symbolp x)) (coerce (symbol-name x) type)) | ||
| 71 | ((eq type 'float) (float x)) | ||
| 72 | ((typep x type) x) | ||
| 73 | (t (error "Can't coerce %s to type %s" x type)))) | ||
| 74 | |||
| 75 | |||
| 76 | ;;; Predicates. | ||
| 77 | |||
| 78 | (defun equalp (x y) | ||
| 79 | "T if two Lisp objects have similar structures and contents. | ||
| 80 | This is like `equal', except that it accepts numerically equal | ||
| 81 | numbers of different types (float vs. integer), and also compares | ||
| 82 | strings case-insensitively." | ||
| 83 | (cond ((eq x y) t) | ||
| 84 | ((stringp x) | ||
| 85 | (and (stringp y) (= (length x) (length y)) | ||
| 86 | (or (equal x y) | ||
| 87 | (equal (downcase x) (downcase y))))) ; lazy but simple! | ||
| 88 | ((numberp x) | ||
| 89 | (and (numberp y) (= x y))) | ||
| 90 | ((consp x) | ||
| 91 | (while (and (consp x) (consp y) (equalp (cl-pop x) (cl-pop y)))) | ||
| 92 | (and (not (consp x)) (equalp x y))) | ||
| 93 | ((vectorp x) | ||
| 94 | (and (vectorp y) (= (length x) (length y)) | ||
| 95 | (let ((i (length x))) | ||
| 96 | (while (and (>= (setq i (1- i)) 0) | ||
| 97 | (equalp (aref x i) (aref y i)))) | ||
| 98 | (< i 0)))) | ||
| 99 | (t (equal x y)))) | ||
| 100 | |||
| 101 | |||
| 102 | ;;; Control structures. | ||
| 103 | |||
| 104 | (defun cl-mapcar-many (cl-func cl-seqs) | ||
| 105 | (if (cdr (cdr cl-seqs)) | ||
| 106 | (let* ((cl-res nil) | ||
| 107 | (cl-n (apply 'min (mapcar 'length cl-seqs))) | ||
| 108 | (cl-i 0) | ||
| 109 | (cl-args (copy-sequence cl-seqs)) | ||
| 110 | cl-p1 cl-p2) | ||
| 111 | (setq cl-seqs (copy-sequence cl-seqs)) | ||
| 112 | (while (< cl-i cl-n) | ||
| 113 | (setq cl-p1 cl-seqs cl-p2 cl-args) | ||
| 114 | (while cl-p1 | ||
| 115 | (setcar cl-p2 | ||
| 116 | (if (consp (car cl-p1)) | ||
| 117 | (prog1 (car (car cl-p1)) | ||
| 118 | (setcar cl-p1 (cdr (car cl-p1)))) | ||
| 119 | (aref (car cl-p1) cl-i))) | ||
| 120 | (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2))) | ||
| 121 | (cl-push (apply cl-func cl-args) cl-res) | ||
| 122 | (setq cl-i (1+ cl-i))) | ||
| 123 | (nreverse cl-res)) | ||
| 124 | (let ((cl-res nil) | ||
| 125 | (cl-x (car cl-seqs)) | ||
| 126 | (cl-y (nth 1 cl-seqs))) | ||
| 127 | (let ((cl-n (min (length cl-x) (length cl-y))) | ||
| 128 | (cl-i -1)) | ||
| 129 | (while (< (setq cl-i (1+ cl-i)) cl-n) | ||
| 130 | (cl-push (funcall cl-func | ||
| 131 | (if (consp cl-x) (cl-pop cl-x) (aref cl-x cl-i)) | ||
| 132 | (if (consp cl-y) (cl-pop cl-y) (aref cl-y cl-i))) | ||
| 133 | cl-res))) | ||
| 134 | (nreverse cl-res)))) | ||
| 135 | |||
| 136 | (defun map (cl-type cl-func cl-seq &rest cl-rest) | ||
| 137 | "Map a function across one or more sequences, returning a sequence. | ||
| 138 | TYPE is the sequence type to return, FUNC is the function, and SEQS | ||
| 139 | are the argument sequences." | ||
| 140 | (let ((cl-res (apply 'mapcar* cl-func cl-seq cl-rest))) | ||
| 141 | (and cl-type (coerce cl-res cl-type)))) | ||
| 142 | |||
| 143 | (defun maplist (cl-func cl-list &rest cl-rest) | ||
| 144 | "Map FUNC to each sublist of LIST or LISTS. | ||
| 145 | Like `mapcar', except applies to lists and their cdr's rather than to | ||
| 146 | the elements themselves." | ||
| 147 | (if cl-rest | ||
| 148 | (let ((cl-res nil) | ||
| 149 | (cl-args (cons cl-list (copy-sequence cl-rest))) | ||
| 150 | cl-p) | ||
| 151 | (while (not (memq nil cl-args)) | ||
| 152 | (cl-push (apply cl-func cl-args) cl-res) | ||
| 153 | (setq cl-p cl-args) | ||
| 154 | (while cl-p (setcar cl-p (cdr (cl-pop cl-p)) ))) | ||
| 155 | (nreverse cl-res)) | ||
| 156 | (let ((cl-res nil)) | ||
| 157 | (while cl-list | ||
| 158 | (cl-push (funcall cl-func cl-list) cl-res) | ||
| 159 | (setq cl-list (cdr cl-list))) | ||
| 160 | (nreverse cl-res)))) | ||
| 161 | |||
| 162 | (defun mapc (cl-func cl-seq &rest cl-rest) | ||
| 163 | "Like `mapcar', but does not accumulate values returned by the function." | ||
| 164 | (if cl-rest | ||
| 165 | (apply 'map nil cl-func cl-seq cl-rest) | ||
| 166 | (mapcar cl-func cl-seq)) | ||
| 167 | cl-seq) | ||
| 168 | |||
| 169 | (defun mapl (cl-func cl-list &rest cl-rest) | ||
| 170 | "Like `maplist', but does not accumulate values returned by the function." | ||
| 171 | (if cl-rest | ||
| 172 | (apply 'maplist cl-func cl-list cl-rest) | ||
| 173 | (let ((cl-p cl-list)) | ||
| 174 | (while cl-p (funcall cl-func cl-p) (setq cl-p (cdr cl-p))))) | ||
| 175 | cl-list) | ||
| 176 | |||
| 177 | (defun mapcan (cl-func cl-seq &rest cl-rest) | ||
| 178 | "Like `mapcar', but nconc's together the values returned by the function." | ||
| 179 | (apply 'nconc (apply 'mapcar* cl-func cl-seq cl-rest))) | ||
| 180 | |||
| 181 | (defun mapcon (cl-func cl-list &rest cl-rest) | ||
| 182 | "Like `maplist', but nconc's together the values returned by the function." | ||
| 183 | (apply 'nconc (apply 'maplist cl-func cl-list cl-rest))) | ||
| 184 | |||
| 185 | (defun some (cl-pred cl-seq &rest cl-rest) | ||
| 186 | "Return true if PREDICATE is true of any element of SEQ or SEQs. | ||
| 187 | If so, return the true (non-nil) value returned by PREDICATE." | ||
| 188 | (if (or cl-rest (nlistp cl-seq)) | ||
| 189 | (catch 'cl-some | ||
| 190 | (apply 'map nil | ||
| 191 | (function (lambda (&rest cl-x) | ||
| 192 | (let ((cl-res (apply cl-pred cl-x))) | ||
| 193 | (if cl-res (throw 'cl-some cl-res))))) | ||
| 194 | cl-seq cl-rest) nil) | ||
| 195 | (let ((cl-x nil)) | ||
| 196 | (while (and cl-seq (not (setq cl-x (funcall cl-pred (cl-pop cl-seq)))))) | ||
| 197 | cl-x))) | ||
| 198 | |||
| 199 | (defun every (cl-pred cl-seq &rest cl-rest) | ||
| 200 | "Return true if PREDICATE is true of every element of SEQ or SEQs." | ||
| 201 | (if (or cl-rest (nlistp cl-seq)) | ||
| 202 | (catch 'cl-every | ||
| 203 | (apply 'map nil | ||
| 204 | (function (lambda (&rest cl-x) | ||
| 205 | (or (apply cl-pred cl-x) (throw 'cl-every nil)))) | ||
| 206 | cl-seq cl-rest) t) | ||
| 207 | (while (and cl-seq (funcall cl-pred (car cl-seq))) | ||
| 208 | (setq cl-seq (cdr cl-seq))) | ||
| 209 | (null cl-seq))) | ||
| 210 | |||
| 211 | (defun notany (cl-pred cl-seq &rest cl-rest) | ||
| 212 | "Return true if PREDICATE is false of every element of SEQ or SEQs." | ||
| 213 | (not (apply 'some cl-pred cl-seq cl-rest))) | ||
| 214 | |||
| 215 | (defun notevery (cl-pred cl-seq &rest cl-rest) | ||
| 216 | "Return true if PREDICATE is false of some element of SEQ or SEQs." | ||
| 217 | (not (apply 'every cl-pred cl-seq cl-rest))) | ||
| 218 | |||
| 219 | ;;; Support for `loop'. | ||
| 220 | (defun cl-map-keymap (cl-func cl-map) | ||
| 221 | (while (symbolp cl-map) (setq cl-map (symbol-function cl-map))) | ||
| 222 | (if (eq cl-emacs-type 'lucid) (funcall 'map-keymap cl-func cl-map) | ||
| 223 | (if (listp cl-map) | ||
| 224 | (let ((cl-p cl-map)) | ||
| 225 | (while (consp (setq cl-p (cdr cl-p))) | ||
| 226 | (cond ((consp (car cl-p)) | ||
| 227 | (funcall cl-func (car (car cl-p)) (cdr (car cl-p)))) | ||
| 228 | ((vectorp (car cl-p)) | ||
| 229 | (cl-map-keymap cl-func (car cl-p))) | ||
| 230 | ((eq (car cl-p) 'keymap) | ||
| 231 | (setq cl-p nil))))) | ||
| 232 | (let ((cl-i -1)) | ||
| 233 | (while (< (setq cl-i (1+ cl-i)) (length cl-map)) | ||
| 234 | (if (aref cl-map cl-i) | ||
| 235 | (funcall cl-func cl-i (aref cl-map cl-i)))))))) | ||
| 236 | |||
| 237 | (defun cl-map-keymap-recursively (cl-func-rec cl-map &optional cl-base) | ||
| 238 | (or cl-base | ||
| 239 | (setq cl-base (copy-sequence (if (eq cl-emacs-type 18) "0" [0])))) | ||
| 240 | (cl-map-keymap | ||
| 241 | (function | ||
| 242 | (lambda (cl-key cl-bind) | ||
| 243 | (aset cl-base (1- (length cl-base)) cl-key) | ||
| 244 | (if (keymapp cl-bind) | ||
| 245 | (cl-map-keymap-recursively | ||
| 246 | cl-func-rec cl-bind | ||
| 247 | (funcall (if (eq cl-emacs-type 18) 'concat 'vconcat) | ||
| 248 | cl-base (list 0))) | ||
| 249 | (funcall cl-func-rec cl-base cl-bind)))) | ||
| 250 | cl-map)) | ||
| 251 | |||
| 252 | (defun cl-map-intervals (cl-func &optional cl-what cl-prop cl-start cl-end) | ||
| 253 | (or cl-what (setq cl-what (current-buffer))) | ||
| 254 | (if (bufferp cl-what) | ||
| 255 | (let (cl-mark cl-mark2 (cl-next t) cl-next2) | ||
| 256 | (save-excursion | ||
| 257 | (set-buffer cl-what) | ||
| 258 | (setq cl-mark (copy-marker (or cl-start (point-min)))) | ||
| 259 | (setq cl-mark2 (and cl-end (copy-marker cl-end)))) | ||
| 260 | (while (and cl-next (or (not cl-mark2) (< cl-mark cl-mark2))) | ||
| 261 | (setq cl-next (and (fboundp 'next-property-change) | ||
| 262 | (if cl-prop (next-single-property-change | ||
| 263 | cl-mark cl-prop cl-what) | ||
| 264 | (next-property-change cl-mark cl-what))) | ||
| 265 | cl-next2 (or cl-next (save-excursion | ||
| 266 | (set-buffer cl-what) (point-max)))) | ||
| 267 | (funcall cl-func (prog1 (marker-position cl-mark) | ||
| 268 | (set-marker cl-mark cl-next2)) | ||
| 269 | (if cl-mark2 (min cl-next2 cl-mark2) cl-next2))) | ||
| 270 | (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))) | ||
| 271 | (or cl-start (setq cl-start 0)) | ||
| 272 | (or cl-end (setq cl-end (length cl-what))) | ||
| 273 | (while (< cl-start cl-end) | ||
| 274 | (let ((cl-next (or (and (fboundp 'next-property-change) | ||
| 275 | (if cl-prop (next-single-property-change | ||
| 276 | cl-start cl-prop cl-what) | ||
| 277 | (next-property-change cl-start cl-what))) | ||
| 278 | cl-end))) | ||
| 279 | (funcall cl-func cl-start (min cl-next cl-end)) | ||
| 280 | (setq cl-start cl-next))))) | ||
| 281 | |||
| 282 | (defun cl-map-overlays (cl-func &optional cl-buffer cl-start cl-end cl-arg) | ||
| 283 | (or cl-buffer (setq cl-buffer (current-buffer))) | ||
| 284 | (if (fboundp 'overlay-lists) | ||
| 285 | |||
| 286 | ;; This is the preferred algorithm, though overlay-lists is undocumented. | ||
| 287 | (let (cl-ovl) | ||
| 288 | (save-excursion | ||
| 289 | (set-buffer cl-buffer) | ||
| 290 | (setq cl-ovl (overlay-lists)) | ||
| 291 | (if cl-start (setq cl-start (copy-marker cl-start))) | ||
| 292 | (if cl-end (setq cl-end (copy-marker cl-end)))) | ||
| 293 | (setq cl-ovl (nconc (car cl-ovl) (cdr cl-ovl))) | ||
| 294 | (while (and cl-ovl | ||
| 295 | (or (not (overlay-start (car cl-ovl))) | ||
| 296 | (and cl-end (>= (overlay-start (car cl-ovl)) cl-end)) | ||
| 297 | (and cl-start (<= (overlay-end (car cl-ovl)) cl-start)) | ||
| 298 | (not (funcall cl-func (car cl-ovl) cl-arg)))) | ||
| 299 | (setq cl-ovl (cdr cl-ovl))) | ||
| 300 | (if cl-start (set-marker cl-start nil)) | ||
| 301 | (if cl-end (set-marker cl-end nil))) | ||
| 302 | |||
| 303 | ;; This alternate algorithm fails to find zero-length overlays. | ||
| 304 | (let ((cl-mark (save-excursion (set-buffer cl-buffer) | ||
| 305 | (copy-marker (or cl-start (point-min))))) | ||
| 306 | (cl-mark2 (and cl-end (save-excursion (set-buffer cl-buffer) | ||
| 307 | (copy-marker cl-end)))) | ||
| 308 | cl-pos cl-ovl) | ||
| 309 | (while (save-excursion | ||
| 310 | (and (setq cl-pos (marker-position cl-mark)) | ||
| 311 | (< cl-pos (or cl-mark2 (point-max))) | ||
| 312 | (progn | ||
| 313 | (set-buffer cl-buffer) | ||
| 314 | (setq cl-ovl (overlays-at cl-pos)) | ||
| 315 | (set-marker cl-mark (next-overlay-change cl-pos))))) | ||
| 316 | (while (and cl-ovl | ||
| 317 | (or (/= (overlay-start (car cl-ovl)) cl-pos) | ||
| 318 | (not (and (funcall cl-func (car cl-ovl) cl-arg) | ||
| 319 | (set-marker cl-mark nil))))) | ||
| 320 | (setq cl-ovl (cdr cl-ovl)))) | ||
| 321 | (set-marker cl-mark nil) (if cl-mark2 (set-marker cl-mark2 nil))))) | ||
| 322 | |||
| 323 | ;;; Support for `setf'. | ||
| 324 | (defun cl-set-frame-visible-p (frame val) | ||
| 325 | (cond ((null val) (make-frame-invisible frame)) | ||
| 326 | ((eq val 'icon) (iconify-frame frame)) | ||
| 327 | (t (make-frame-visible frame))) | ||
| 328 | val) | ||
| 329 | |||
| 330 | ;;; Support for `progv'. | ||
| 331 | (defvar cl-progv-save) | ||
| 332 | (defun cl-progv-before (syms values) | ||
| 333 | (while syms | ||
| 334 | (cl-push (if (boundp (car syms)) | ||
| 335 | (cons (car syms) (symbol-value (car syms))) | ||
| 336 | (car syms)) cl-progv-save) | ||
| 337 | (if values | ||
| 338 | (set (cl-pop syms) (cl-pop values)) | ||
| 339 | (makunbound (cl-pop syms))))) | ||
| 340 | |||
| 341 | (defun cl-progv-after () | ||
| 342 | (while cl-progv-save | ||
| 343 | (if (consp (car cl-progv-save)) | ||
| 344 | (set (car (car cl-progv-save)) (cdr (car cl-progv-save))) | ||
| 345 | (makunbound (car cl-progv-save))) | ||
| 346 | (cl-pop cl-progv-save))) | ||
| 347 | |||
| 348 | |||
| 349 | ;;; Numbers. | ||
| 350 | |||
| 351 | (defun gcd (&rest args) | ||
| 352 | "Return the greatest common divisor of the arguments." | ||
| 353 | (let ((a (abs (or (cl-pop args) 0)))) | ||
| 354 | (while args | ||
| 355 | (let ((b (abs (cl-pop args)))) | ||
| 356 | (while (> b 0) (setq b (% a (setq a b)))))) | ||
| 357 | a)) | ||
| 358 | |||
| 359 | (defun lcm (&rest args) | ||
| 360 | "Return the least common multiple of the arguments." | ||
| 361 | (if (memq 0 args) | ||
| 362 | 0 | ||
| 363 | (let ((a (abs (or (cl-pop args) 1)))) | ||
| 364 | (while args | ||
| 365 | (let ((b (abs (cl-pop args)))) | ||
| 366 | (setq a (* (/ a (gcd a b)) b)))) | ||
| 367 | a))) | ||
| 368 | |||
| 369 | (defun isqrt (a) | ||
| 370 | "Return the integer square root of the argument." | ||
| 371 | (if (and (integerp a) (> a 0)) | ||
| 372 | (let ((g (cond ((>= a 1000000) 10000) ((>= a 10000) 1000) | ||
| 373 | ((>= a 100) 100) (t 10))) | ||
| 374 | g2) | ||
| 375 | (while (< (setq g2 (/ (+ g (/ a g)) 2)) g) | ||
| 376 | (setq g g2)) | ||
| 377 | g) | ||
| 378 | (if (eq a 0) 0 (signal 'arith-error nil)))) | ||
| 379 | |||
| 380 | (defun cl-expt (x y) | ||
| 381 | "Return X raised to the power of Y. Works only for integer arguments." | ||
| 382 | (if (<= y 0) (if (= y 0) 1 (if (memq x '(-1 1)) x 0)) | ||
| 383 | (* (if (= (% y 2) 0) 1 x) (cl-expt (* x x) (/ y 2))))) | ||
| 384 | (or (and (fboundp 'expt) (subrp (symbol-function 'expt))) | ||
| 385 | (defalias 'expt 'cl-expt)) | ||
| 386 | |||
| 387 | (defun floor* (x &optional y) | ||
| 388 | "Return a list of the floor of X and the fractional part of X. | ||
| 389 | With two arguments, return floor and remainder of their quotient." | ||
| 390 | (if y | ||
| 391 | (if (and (integerp x) (integerp y)) | ||
| 392 | (if (and (>= x 0) (>= y 0)) | ||
| 393 | (list (/ x y) (% x y)) | ||
| 394 | (let ((q (cond ((>= x 0) (- (/ (- x y 1) (- y)))) | ||
| 395 | ((>= y 0) (- (/ (- y x 1) y))) | ||
| 396 | (t (/ (- x) (- y)))))) | ||
| 397 | (list q (- x (* q y))))) | ||
| 398 | (let ((q (floor (/ x y)))) | ||
| 399 | (list q (- x (* q y))))) | ||
| 400 | (if (integerp x) (list x 0) | ||
| 401 | (let ((q (floor x))) | ||
| 402 | (list q (- x q)))))) | ||
| 403 | |||
| 404 | (defun ceiling* (x &optional y) | ||
| 405 | "Return a list of the ceiling of X and the fractional part of X. | ||
| 406 | With two arguments, return ceiling and remainder of their quotient." | ||
| 407 | (let ((res (floor* x y))) | ||
| 408 | (if (= (car (cdr res)) 0) res | ||
| 409 | (list (1+ (car res)) (- (car (cdr res)) (or y 1)))))) | ||
| 410 | |||
| 411 | (defun truncate* (x &optional y) | ||
| 412 | "Return a list of the integer part of X and the fractional part of X. | ||
| 413 | With two arguments, return truncation and remainder of their quotient." | ||
| 414 | (if (eq (>= x 0) (or (null y) (>= y 0))) | ||
| 415 | (floor* x y) (ceiling* x y))) | ||
| 416 | |||
| 417 | (defun round* (x &optional y) | ||
| 418 | "Return a list of X rounded to the nearest integer and the remainder. | ||
| 419 | With two arguments, return rounding and remainder of their quotient." | ||
| 420 | (if y | ||
| 421 | (if (and (integerp x) (integerp y)) | ||
| 422 | (let* ((hy (/ y 2)) | ||
| 423 | (res (floor* (+ x hy) y))) | ||
| 424 | (if (and (= (car (cdr res)) 0) | ||
| 425 | (= (+ hy hy) y) | ||
| 426 | (/= (% (car res) 2) 0)) | ||
| 427 | (list (1- (car res)) hy) | ||
| 428 | (list (car res) (- (car (cdr res)) hy)))) | ||
| 429 | (let ((q (round (/ x y)))) | ||
| 430 | (list q (- x (* q y))))) | ||
| 431 | (if (integerp x) (list x 0) | ||
| 432 | (let ((q (round x))) | ||
| 433 | (list q (- x q)))))) | ||
| 434 | |||
| 435 | (defun mod* (x y) | ||
| 436 | "The remainder of X divided by Y, with the same sign as Y." | ||
| 437 | (nth 1 (floor* x y))) | ||
| 438 | |||
| 439 | (defun rem* (x y) | ||
| 440 | "The remainder of X divided by Y, with the same sign as X." | ||
| 441 | (nth 1 (truncate* x y))) | ||
| 442 | |||
| 443 | (defun signum (a) | ||
| 444 | "Return 1 if A is positive, -1 if negative, 0 if zero." | ||
| 445 | (cond ((> a 0) 1) ((< a 0) -1) (t 0))) | ||
| 446 | |||
| 447 | |||
| 448 | ;; Random numbers. | ||
| 449 | |||
| 450 | (defvar *random-state*) | ||
| 451 | (defun random* (lim &optional state) | ||
| 452 | "Return a random nonnegative number less than LIM, an integer or float. | ||
| 453 | Optional second arg STATE is a random-state object." | ||
| 454 | (or state (setq state *random-state*)) | ||
| 455 | ;; Inspired by "ran3" from Numerical Recipes. Additive congruential method. | ||
| 456 | (let ((vec (aref state 3))) | ||
| 457 | (if (integerp vec) | ||
| 458 | (let ((i 0) (j (- 1357335 (% (abs vec) 1357333))) (k 1) ii) | ||
| 459 | (aset state 3 (setq vec (make-vector 55 nil))) | ||
| 460 | (aset vec 0 j) | ||
| 461 | (while (> (setq i (% (+ i 21) 55)) 0) | ||
| 462 | (aset vec i (setq j (prog1 k (setq k (- j k)))))) | ||
| 463 | (while (< (setq i (1+ i)) 200) (random* 2 state)))) | ||
| 464 | (let* ((i (aset state 1 (% (1+ (aref state 1)) 55))) | ||
| 465 | (j (aset state 2 (% (1+ (aref state 2)) 55))) | ||
| 466 | (n (logand 8388607 (aset vec i (- (aref vec i) (aref vec j)))))) | ||
| 467 | (if (integerp lim) | ||
| 468 | (if (<= lim 512) (% n lim) | ||
| 469 | (if (> lim 8388607) (setq n (+ (lsh n 9) (random* 512 state)))) | ||
| 470 | (let ((mask 1023)) | ||
| 471 | (while (< mask (1- lim)) (setq mask (1+ (+ mask mask)))) | ||
| 472 | (if (< (setq n (logand n mask)) lim) n (random* lim state)))) | ||
| 473 | (* (/ n '8388608e0) lim))))) | ||
| 474 | |||
| 475 | (defun make-random-state (&optional state) | ||
| 476 | "Return a copy of random-state STATE, or of `*random-state*' if omitted. | ||
| 477 | If STATE is t, return a new state object seeded from the time of day." | ||
| 478 | (cond ((null state) (make-random-state *random-state*)) | ||
| 479 | ((vectorp state) (cl-copy-tree state t)) | ||
| 480 | ((integerp state) (vector 'cl-random-state-tag -1 30 state)) | ||
| 481 | (t (make-random-state (cl-random-time))))) | ||
| 482 | |||
| 483 | (defun random-state-p (object) | ||
| 484 | "Return t if OBJECT is a random-state object." | ||
| 485 | (and (vectorp object) (= (length object) 4) | ||
| 486 | (eq (aref object 0) 'cl-random-state-tag))) | ||
| 487 | |||
| 488 | |||
| 489 | ;; Implementation limits. | ||
| 490 | |||
| 491 | (defun cl-finite-do (func a b) | ||
| 492 | (condition-case err | ||
| 493 | (let ((res (funcall func a b))) ; check for IEEE infinity | ||
| 494 | (and (numberp res) (/= res (/ res 2)) res)) | ||
| 495 | (arith-error nil))) | ||
| 496 | |||
| 497 | (defvar most-positive-float) | ||
| 498 | (defvar most-negative-float) | ||
| 499 | (defvar least-positive-float) | ||
| 500 | (defvar least-negative-float) | ||
| 501 | (defvar least-positive-normalized-float) | ||
| 502 | (defvar least-negative-normalized-float) | ||
| 503 | (defvar float-epsilon) | ||
| 504 | (defvar float-negative-epsilon) | ||
| 505 | |||
| 506 | (defun cl-float-limits () | ||
| 507 | (or most-positive-float (not (numberp '2e1)) | ||
| 508 | (let ((x '2e0) y z) | ||
| 509 | ;; Find maximum exponent (first two loops are optimizations) | ||
| 510 | (while (cl-finite-do '* x x) (setq x (* x x))) | ||
| 511 | (while (cl-finite-do '* x (/ x 2)) (setq x (* x (/ x 2)))) | ||
| 512 | (while (cl-finite-do '+ x x) (setq x (+ x x))) | ||
| 513 | (setq z x y (/ x 2)) | ||
| 514 | ;; Now fill in 1's in the mantissa. | ||
| 515 | (while (and (cl-finite-do '+ x y) (/= (+ x y) x)) | ||
| 516 | (setq x (+ x y) y (/ y 2))) | ||
| 517 | (setq most-positive-float x | ||
| 518 | most-negative-float (- x)) | ||
| 519 | ;; Divide down until mantissa starts rounding. | ||
| 520 | (setq x (/ x z) y (/ 16 z) x (* x y)) | ||
| 521 | (while (condition-case err (and (= x (* (/ x 2) 2)) (> (/ y 2) 0)) | ||
| 522 | (arith-error nil)) | ||
| 523 | (setq x (/ x 2) y (/ y 2))) | ||
| 524 | (setq least-positive-normalized-float y | ||
| 525 | least-negative-normalized-float (- y)) | ||
| 526 | ;; Divide down until value underflows to zero. | ||
| 527 | (setq x (/ 1 z) y x) | ||
| 528 | (while (condition-case err (> (/ x 2) 0) (arith-error nil)) | ||
| 529 | (setq x (/ x 2))) | ||
| 530 | (setq least-positive-float x | ||
| 531 | least-negative-float (- x)) | ||
| 532 | (setq x '1e0) | ||
| 533 | (while (/= (+ '1e0 x) '1e0) (setq x (/ x 2))) | ||
| 534 | (setq float-epsilon (* x 2)) | ||
| 535 | (setq x '1e0) | ||
| 536 | (while (/= (- '1e0 x) '1e0) (setq x (/ x 2))) | ||
| 537 | (setq float-negative-epsilon (* x 2)))) | ||
| 538 | nil) | ||
| 539 | |||
| 540 | |||
| 541 | ;;; Sequence functions. | ||
| 542 | |||
| 543 | (defun subseq (seq start &optional end) | ||
| 544 | "Return the subsequence of SEQ from START to END. | ||
| 545 | If END is omitted, it defaults to the length of the sequence. | ||
| 546 | If START or END is negative, it counts from the end." | ||
| 547 | (if (stringp seq) (substring seq start end) | ||
| 548 | (let (len) | ||
| 549 | (and end (< end 0) (setq end (+ end (setq len (length seq))))) | ||
| 550 | (if (< start 0) (setq start (+ start (or len (setq len (length seq)))))) | ||
| 551 | (cond ((listp seq) | ||
| 552 | (if (> start 0) (setq seq (nthcdr start seq))) | ||
| 553 | (if end | ||
| 554 | (let ((res nil)) | ||
| 555 | (while (>= (setq end (1- end)) start) | ||
| 556 | (cl-push (cl-pop seq) res)) | ||
| 557 | (nreverse res)) | ||
| 558 | (copy-sequence seq))) | ||
| 559 | (t | ||
| 560 | (or end (setq end (or len (length seq)))) | ||
| 561 | (let ((res (make-vector (max (- end start) 0) nil)) | ||
| 562 | (i 0)) | ||
| 563 | (while (< start end) | ||
| 564 | (aset res i (aref seq start)) | ||
| 565 | (setq i (1+ i) start (1+ start))) | ||
| 566 | res)))))) | ||
| 567 | |||
| 568 | (defun concatenate (type &rest seqs) | ||
| 569 | "Concatenate, into a sequence of type TYPE, the argument SEQUENCES." | ||
| 570 | (cond ((eq type 'vector) (apply 'vconcat seqs)) | ||
| 571 | ((eq type 'string) (apply 'concat seqs)) | ||
| 572 | ((eq type 'list) (apply 'append (append seqs '(nil)))) | ||
| 573 | (t (error "Not a sequence type name: %s" type)))) | ||
| 574 | |||
| 575 | |||
| 576 | ;;; List functions. | ||
| 577 | |||
| 578 | (defun revappend (x y) | ||
| 579 | "Equivalent to (append (reverse X) Y)." | ||
| 580 | (nconc (reverse x) y)) | ||
| 581 | |||
| 582 | (defun nreconc (x y) | ||
| 583 | "Equivalent to (nconc (nreverse X) Y)." | ||
| 584 | (nconc (nreverse x) y)) | ||
| 585 | |||
| 586 | (defun list-length (x) | ||
| 587 | "Return the length of a list. Return nil if list is circular." | ||
| 588 | (let ((n 0) (fast x) (slow x)) | ||
| 589 | (while (and (cdr fast) (not (and (eq fast slow) (> n 0)))) | ||
| 590 | (setq n (+ n 2) fast (cdr (cdr fast)) slow (cdr slow))) | ||
| 591 | (if fast (if (cdr fast) nil (1+ n)) n))) | ||
| 592 | |||
| 593 | (defun tailp (sublist list) | ||
| 594 | "Return true if SUBLIST is a tail of LIST." | ||
| 595 | (while (and (consp list) (not (eq sublist list))) | ||
| 596 | (setq list (cdr list))) | ||
| 597 | (if (numberp sublist) (equal sublist list) (eq sublist list))) | ||
| 598 | |||
| 599 | (defun cl-copy-tree (tree &optional vecp) | ||
| 600 | "Make a copy of TREE. | ||
| 601 | If TREE is a cons cell, this recursively copies both its car and its cdr. | ||
| 602 | Constrast to copy-sequence, which copies only along the cdrs. With second | ||
| 603 | argument VECP, this copies vectors as well as conses." | ||
| 604 | (if (consp tree) | ||
| 605 | (let ((p (setq tree (copy-list tree)))) | ||
| 606 | (while (consp p) | ||
| 607 | (if (or (consp (car p)) (and vecp (vectorp (car p)))) | ||
| 608 | (setcar p (cl-copy-tree (car p) vecp))) | ||
| 609 | (or (listp (cdr p)) (setcdr p (cl-copy-tree (cdr p) vecp))) | ||
| 610 | (cl-pop p))) | ||
| 611 | (if (and vecp (vectorp tree)) | ||
| 612 | (let ((i (length (setq tree (copy-sequence tree))))) | ||
| 613 | (while (>= (setq i (1- i)) 0) | ||
| 614 | (aset tree i (cl-copy-tree (aref tree i) vecp)))))) | ||
| 615 | tree) | ||
| 616 | (or (and (fboundp 'copy-tree) (subrp (symbol-function 'copy-tree))) | ||
| 617 | (defalias 'copy-tree 'cl-copy-tree)) | ||
| 618 | |||
| 619 | |||
| 620 | ;;; Property lists. | ||
| 621 | |||
| 622 | (defun get* (sym tag &optional def) ; See compiler macro in cl-macs.el | ||
| 623 | "Return the value of SYMBOL's PROPNAME property, or DEFAULT if none." | ||
| 624 | (or (get sym tag) | ||
| 625 | (and def | ||
| 626 | (let ((plist (symbol-plist sym))) | ||
| 627 | (while (and plist (not (eq (car plist) tag))) | ||
| 628 | (setq plist (cdr (cdr plist)))) | ||
| 629 | (if plist (car (cdr plist)) def))))) | ||
| 630 | |||
| 631 | (defun getf (plist tag &optional def) | ||
| 632 | "Search PROPLIST for property PROPNAME; return its value or DEFAULT. | ||
| 633 | PROPLIST is a list of the sort returned by `symbol-plist'." | ||
| 634 | (setplist '--cl-getf-symbol-- plist) | ||
| 635 | (or (get '--cl-getf-symbol-- tag) | ||
| 636 | (and def (get* '--cl-getf-symbol-- tag def)))) | ||
| 637 | |||
| 638 | (defun cl-set-getf (plist tag val) | ||
| 639 | (let ((p plist)) | ||
| 640 | (while (and p (not (eq (car p) tag))) (setq p (cdr (cdr p)))) | ||
| 641 | (if p (progn (setcar (cdr p) val) plist) (list* tag val plist)))) | ||
| 642 | |||
| 643 | (defun cl-do-remf (plist tag) | ||
| 644 | (let ((p (cdr plist))) | ||
| 645 | (while (and (cdr p) (not (eq (car (cdr p)) tag))) (setq p (cdr (cdr p)))) | ||
| 646 | (and (cdr p) (progn (setcdr p (cdr (cdr (cdr p)))) t)))) | ||
| 647 | |||
| 648 | (defun cl-remprop (sym tag) | ||
| 649 | "Remove from SYMBOL's plist the property PROP and its value." | ||
| 650 | (let ((plist (symbol-plist sym))) | ||
| 651 | (if (and plist (eq tag (car plist))) | ||
| 652 | (progn (setplist sym (cdr (cdr plist))) t) | ||
| 653 | (cl-do-remf plist tag)))) | ||
| 654 | (or (and (fboundp 'remprop) (subrp (symbol-function 'remprop))) | ||
| 655 | (defalias 'remprop 'cl-remprop)) | ||
| 656 | |||
| 657 | |||
| 658 | |||
| 659 | ;;; Hash tables. | ||
| 660 | |||
| 661 | (defun make-hash-table (&rest cl-keys) | ||
| 662 | "Make an empty Common Lisp-style hash-table. | ||
| 663 | If :test is `eq', this can use Lucid Emacs built-in hash-tables. | ||
| 664 | In non-Lucid Emacs, or with non-`eq' test, this internally uses a-lists. | ||
| 665 | Keywords supported: :test :size | ||
| 666 | The Common Lisp keywords :rehash-size and :rehash-threshold are ignored." | ||
| 667 | (let ((cl-test (or (car (cdr (memq ':test cl-keys))) 'eql)) | ||
| 668 | (cl-size (or (car (cdr (memq ':size cl-keys))) 20))) | ||
| 669 | (if (and (eq cl-test 'eq) (fboundp 'make-hashtable)) | ||
| 670 | (funcall 'make-hashtable cl-size) | ||
| 671 | (list 'cl-hash-table-tag cl-test | ||
| 672 | (if (> cl-size 1) (make-vector cl-size 0) | ||
| 673 | (let ((sym (make-symbol "--hashsym--"))) (set sym nil) sym)) | ||
| 674 | 0)))) | ||
| 675 | |||
| 676 | (defvar cl-lucid-hash-tag | ||
| 677 | (if (and (fboundp 'make-hashtable) (vectorp (make-hashtable 1))) | ||
| 678 | (aref (make-hashtable 1) 0) (make-symbol "--cl-hash-tag--"))) | ||
| 679 | |||
| 680 | (defun hash-table-p (x) | ||
| 681 | "Return t if OBJECT is a hash table." | ||
| 682 | (or (eq (car-safe x) 'cl-hash-table-tag) | ||
| 683 | (and (vectorp x) (= (length x) 4) (eq (aref x 0) cl-lucid-hash-tag)) | ||
| 684 | (and (fboundp 'hashtablep) (funcall 'hashtablep x)))) | ||
| 685 | |||
| 686 | (defun cl-not-hash-table (x &optional y &rest z) | ||
| 687 | (signal 'wrong-type-argument (list 'hash-table-p (or y x)))) | ||
| 688 | |||
| 689 | (defun cl-hash-lookup (key table) | ||
| 690 | (or (eq (car-safe table) 'cl-hash-table-tag) (cl-not-hash-table table)) | ||
| 691 | (let* ((array (nth 2 table)) (test (car (cdr table))) (str key) sym) | ||
| 692 | (if (symbolp array) (setq str nil sym (symbol-value array)) | ||
| 693 | (while (or (consp str) (and (vectorp str) (> (length str) 0))) | ||
| 694 | (setq str (elt str 0))) | ||
| 695 | (cond ((stringp str) (if (eq test 'equalp) (setq str (downcase str)))) | ||
| 696 | ((symbolp str) (setq str (symbol-name str))) | ||
| 697 | ((and (numberp str) (> str -8000000) (< str 8000000)) | ||
| 698 | (or (integerp str) (setq str (truncate str))) | ||
| 699 | (setq str (aref ["0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" | ||
| 700 | "11" "12" "13" "14" "15"] (logand str 15)))) | ||
| 701 | (t (setq str "*"))) | ||
| 702 | (setq sym (symbol-value (intern-soft str array)))) | ||
| 703 | (list (and sym (cond ((or (eq test 'eq) | ||
| 704 | (and (eq test 'eql) (not (numberp key)))) | ||
| 705 | (assq key sym)) | ||
| 706 | ((memq test '(eql equal)) (assoc key sym)) | ||
| 707 | (t (assoc* key sym ':test test)))) | ||
| 708 | sym str))) | ||
| 709 | |||
| 710 | (defvar cl-builtin-gethash | ||
| 711 | (if (and (fboundp 'gethash) (subrp (symbol-function 'gethash))) | ||
| 712 | (symbol-function 'gethash) 'cl-not-hash-table)) | ||
| 713 | (defvar cl-builtin-remhash | ||
| 714 | (if (and (fboundp 'remhash) (subrp (symbol-function 'remhash))) | ||
| 715 | (symbol-function 'remhash) 'cl-not-hash-table)) | ||
| 716 | (defvar cl-builtin-clrhash | ||
| 717 | (if (and (fboundp 'clrhash) (subrp (symbol-function 'clrhash))) | ||
| 718 | (symbol-function 'clrhash) 'cl-not-hash-table)) | ||
| 719 | (defvar cl-builtin-maphash | ||
| 720 | (if (and (fboundp 'maphash) (subrp (symbol-function 'maphash))) | ||
| 721 | (symbol-function 'maphash) 'cl-not-hash-table)) | ||
| 722 | |||
| 723 | (defun cl-gethash (key table &optional def) | ||
| 724 | "Look up KEY in HASH-TABLE; return corresponding value, or DEFAULT." | ||
| 725 | (if (consp table) | ||
| 726 | (let ((found (cl-hash-lookup key table))) | ||
| 727 | (if (car found) (cdr (car found)) def)) | ||
| 728 | (funcall cl-builtin-gethash key table def))) | ||
| 729 | (defalias 'gethash 'cl-gethash) | ||
| 730 | |||
| 731 | (defun cl-puthash (key val table) | ||
| 732 | (if (consp table) | ||
| 733 | (let ((found (cl-hash-lookup key table))) | ||
| 734 | (if (car found) (setcdr (car found) val) | ||
| 735 | (if (nth 2 found) | ||
| 736 | (progn | ||
| 737 | (if (> (nth 3 table) (* (length (nth 2 table)) 3)) | ||
| 738 | (let ((new-table (make-vector (nth 3 table) 0))) | ||
| 739 | (mapatoms (function | ||
| 740 | (lambda (sym) | ||
| 741 | (set (intern (symbol-name sym) new-table) | ||
| 742 | (symbol-value sym)))) | ||
| 743 | (nth 2 table)) | ||
| 744 | (setcar (cdr (cdr table)) new-table))) | ||
| 745 | (set (intern (nth 2 found) (nth 2 table)) | ||
| 746 | (cons (cons key val) (nth 1 found)))) | ||
| 747 | (set (nth 2 table) (cons (cons key val) (nth 1 found)))) | ||
| 748 | (setcar (cdr (cdr (cdr table))) (1+ (nth 3 table))))) | ||
| 749 | (funcall 'puthash key val table)) val) | ||
| 750 | |||
| 751 | (defun cl-remhash (key table) | ||
| 752 | "Remove KEY from HASH-TABLE." | ||
| 753 | (if (consp table) | ||
| 754 | (let ((found (cl-hash-lookup key table))) | ||
| 755 | (and (car found) | ||
| 756 | (let ((del (delq (car found) (nth 1 found)))) | ||
| 757 | (setcar (cdr (cdr (cdr table))) (1- (nth 3 table))) | ||
| 758 | (if (nth 2 found) (set (intern (nth 2 found) (nth 2 table)) del) | ||
| 759 | (set (nth 2 table) del)) t))) | ||
| 760 | (prog1 (not (eq (funcall cl-builtin-gethash key table '--cl--) '--cl--)) | ||
| 761 | (funcall cl-builtin-remhash key table)))) | ||
| 762 | (defalias 'remhash 'cl-remhash) | ||
| 763 | |||
| 764 | (defun cl-clrhash (table) | ||
| 765 | "Clear HASH-TABLE." | ||
| 766 | (if (consp table) | ||
| 767 | (progn | ||
| 768 | (or (hash-table-p table) (cl-not-hash-table table)) | ||
| 769 | (if (symbolp (nth 2 table)) (set (nth 2 table) nil) | ||
| 770 | (setcar (cdr (cdr table)) (make-vector (length (nth 2 table)) 0))) | ||
| 771 | (setcar (cdr (cdr (cdr table))) 0)) | ||
| 772 | (funcall cl-builtin-clrhash table)) | ||
| 773 | nil) | ||
| 774 | (defalias 'clrhash 'cl-clrhash) | ||
| 775 | |||
| 776 | (defun cl-maphash (cl-func cl-table) | ||
| 777 | "Call FUNCTION on keys and values from HASH-TABLE." | ||
| 778 | (or (hash-table-p cl-table) (cl-not-hash-table cl-table)) | ||
| 779 | (if (consp cl-table) | ||
| 780 | (mapatoms (function (lambda (cl-x) | ||
| 781 | (setq cl-x (symbol-value cl-x)) | ||
| 782 | (while cl-x | ||
| 783 | (funcall cl-func (car (car cl-x)) | ||
| 784 | (cdr (car cl-x))) | ||
| 785 | (setq cl-x (cdr cl-x))))) | ||
| 786 | (if (symbolp (nth 2 cl-table)) | ||
| 787 | (vector (nth 2 cl-table)) (nth 2 cl-table))) | ||
| 788 | (funcall cl-builtin-maphash cl-func cl-table))) | ||
| 789 | (defalias 'maphash 'cl-maphash) | ||
| 790 | |||
| 791 | (defun hash-table-count (table) | ||
| 792 | "Return the number of entries in HASH-TABLE." | ||
| 793 | (or (hash-table-p table) (cl-not-hash-table table)) | ||
| 794 | (if (consp table) (nth 3 table) (funcall 'hashtable-fullness table))) | ||
| 795 | |||
| 796 | |||
| 797 | ;;; Some debugging aids. | ||
| 798 | |||
| 799 | (defun cl-prettyprint (form) | ||
| 800 | "Insert a pretty-printed rendition of a Lisp FORM in current buffer." | ||
| 801 | (let ((pt (point)) last) | ||
| 802 | (insert "\n" (prin1-to-string form) "\n") | ||
| 803 | (setq last (point)) | ||
| 804 | (goto-char (1+ pt)) | ||
| 805 | (while (search-forward "(quote " last t) | ||
| 806 | (delete-backward-char 7) | ||
| 807 | (insert "'") | ||
| 808 | (forward-sexp) | ||
| 809 | (delete-char 1)) | ||
| 810 | (goto-char (1+ pt)) | ||
| 811 | (cl-do-prettyprint))) | ||
| 812 | |||
| 813 | (defun cl-do-prettyprint () | ||
| 814 | (skip-chars-forward " ") | ||
| 815 | (if (looking-at "(") | ||
| 816 | (let ((skip (or (looking-at "((") (looking-at "(prog") | ||
| 817 | (looking-at "(unwind-protect ") | ||
| 818 | (looking-at "(function (") | ||
| 819 | (looking-at "(cl-block-wrapper "))) | ||
| 820 | (two (or (looking-at "(defun ") (looking-at "(defmacro "))) | ||
| 821 | (let (or (looking-at "(let\\*? ") (looking-at "(while "))) | ||
| 822 | (set (looking-at "(p?set[qf] "))) | ||
| 823 | (if (or skip let | ||
| 824 | (progn | ||
| 825 | (forward-sexp) | ||
| 826 | (and (>= (current-column) 78) (progn (backward-sexp) t)))) | ||
| 827 | (let ((nl t)) | ||
| 828 | (forward-char 1) | ||
| 829 | (cl-do-prettyprint) | ||
| 830 | (or skip (looking-at ")") (cl-do-prettyprint)) | ||
| 831 | (or (not two) (looking-at ")") (cl-do-prettyprint)) | ||
| 832 | (while (not (looking-at ")")) | ||
| 833 | (if set (setq nl (not nl))) | ||
| 834 | (if nl (insert "\n")) | ||
| 835 | (lisp-indent-line) | ||
| 836 | (cl-do-prettyprint)) | ||
| 837 | (forward-char 1)))) | ||
| 838 | (forward-sexp))) | ||
| 839 | |||
| 840 | (defvar cl-macroexpand-cmacs nil) | ||
| 841 | (defvar cl-closure-vars nil) | ||
| 842 | |||
| 843 | (defun cl-macroexpand-all (form &optional env) | ||
| 844 | "Expand all macro calls through a Lisp FORM. | ||
| 845 | This also does some trivial optimizations to make the form prettier." | ||
| 846 | (while (or (not (eq form (setq form (macroexpand form env)))) | ||
| 847 | (and cl-macroexpand-cmacs | ||
| 848 | (not (eq form (setq form (compiler-macroexpand form))))))) | ||
| 849 | (cond ((not (consp form)) form) | ||
| 850 | ((memq (car form) '(let let*)) | ||
| 851 | (if (null (nth 1 form)) | ||
| 852 | (cl-macroexpand-all (cons 'progn (cddr form)) env) | ||
| 853 | (let ((letf nil) (res nil) (lets (cadr form))) | ||
| 854 | (while lets | ||
| 855 | (cl-push (if (consp (car lets)) | ||
| 856 | (let ((exp (cl-macroexpand-all (caar lets) env))) | ||
| 857 | (or (symbolp exp) (setq letf t)) | ||
| 858 | (cons exp (cl-macroexpand-body (cdar lets) env))) | ||
| 859 | (let ((exp (cl-macroexpand-all (car lets) env))) | ||
| 860 | (if (symbolp exp) exp | ||
| 861 | (setq letf t) (list exp nil)))) res) | ||
| 862 | (setq lets (cdr lets))) | ||
| 863 | (list* (if letf (if (eq (car form) 'let) 'letf 'letf*) (car form)) | ||
| 864 | (nreverse res) (cl-macroexpand-body (cddr form) env))))) | ||
| 865 | ((eq (car form) 'cond) | ||
| 866 | (cons (car form) | ||
| 867 | (mapcar (function (lambda (x) (cl-macroexpand-body x env))) | ||
| 868 | (cdr form)))) | ||
| 869 | ((eq (car form) 'condition-case) | ||
| 870 | (list* (car form) (nth 1 form) (cl-macroexpand-all (nth 2 form) env) | ||
| 871 | (mapcar (function | ||
| 872 | (lambda (x) | ||
| 873 | (cons (car x) (cl-macroexpand-body (cdr x) env)))) | ||
| 874 | (cdddr form)))) | ||
| 875 | ((memq (car form) '(quote function)) | ||
| 876 | (if (eq (car-safe (nth 1 form)) 'lambda) | ||
| 877 | (let ((body (cl-macroexpand-body (cddadr form) env))) | ||
| 878 | (if (and cl-closure-vars (eq (car form) 'function) | ||
| 879 | (cl-expr-contains-any body cl-closure-vars)) | ||
| 880 | (let* ((new (mapcar 'gensym cl-closure-vars)) | ||
| 881 | (sub (pairlis cl-closure-vars new)) (decls nil)) | ||
| 882 | (while (or (stringp (car body)) | ||
| 883 | (eq (car-safe (car body)) 'interactive)) | ||
| 884 | (cl-push (list 'quote (cl-pop body)) decls)) | ||
| 885 | (put (car (last cl-closure-vars)) 'used t) | ||
| 886 | (append | ||
| 887 | (list 'list '(quote lambda) '(quote (&rest --cl-rest--))) | ||
| 888 | (sublis sub (nreverse decls)) | ||
| 889 | (list | ||
| 890 | (list* 'list '(quote apply) | ||
| 891 | (list 'list '(quote quote) | ||
| 892 | (list 'function | ||
| 893 | (list* 'lambda | ||
| 894 | (append new (cadadr form)) | ||
| 895 | (sublis sub body)))) | ||
| 896 | (nconc (mapcar (function | ||
| 897 | (lambda (x) | ||
| 898 | (list 'list '(quote quote) x))) | ||
| 899 | cl-closure-vars) | ||
| 900 | '((quote --cl-rest--))))))) | ||
| 901 | (list (car form) (list* 'lambda (cadadr form) body)))) | ||
| 902 | form)) | ||
| 903 | ((memq (car form) '(defun defmacro)) | ||
| 904 | (list* (car form) (nth 1 form) (cl-macroexpand-body (cddr form) env))) | ||
| 905 | ((and (eq (car form) 'progn) (not (cddr form))) | ||
| 906 | (cl-macroexpand-all (nth 1 form) env)) | ||
| 907 | ((eq (car form) 'setq) | ||
| 908 | (let* ((args (cl-macroexpand-body (cdr form) env)) (p args)) | ||
| 909 | (while (and p (symbolp (car p))) (setq p (cddr p))) | ||
| 910 | (if p (cl-macroexpand-all (cons 'setf args)) (cons 'setq args)))) | ||
| 911 | (t (cons (car form) (cl-macroexpand-body (cdr form) env))))) | ||
| 912 | |||
| 913 | (defun cl-macroexpand-body (body &optional env) | ||
| 914 | (mapcar (function (lambda (x) (cl-macroexpand-all x env))) body)) | ||
| 915 | |||
| 916 | (defun cl-prettyexpand (form &optional full) | ||
| 917 | (message "Expanding...") | ||
| 918 | (let ((cl-macroexpand-cmacs full) (cl-compiling-file full) | ||
| 919 | (byte-compile-macro-environment nil)) | ||
| 920 | (setq form (cl-macroexpand-all form | ||
| 921 | (and (not full) '((block) (eval-when))))) | ||
| 922 | (message "Formatting...") | ||
| 923 | (prog1 (cl-prettyprint form) | ||
| 924 | (message "")))) | ||
| 925 | |||
| 926 | |||
| 927 | |||
| 928 | (run-hooks 'cl-extra-load-hook) | ||
| 929 | |||
| 930 | ;;; cl-extra.el ends here | ||
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el new file mode 100644 index 00000000000..552bf0db465 --- /dev/null +++ b/lisp/emacs-lisp/cl-macs.el | |||
| @@ -0,0 +1,2610 @@ | |||
| 1 | ;; cl-macs.el --- Common Lisp extensions for GNU Emacs Lisp (part four) | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Dave Gillespie <daveg@synaptics.com> | ||
| 6 | ;; Version: 2.02 | ||
| 7 | ;; Keywords: extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 14 | ;; any later version. | ||
| 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 | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | ;; Commentary: | ||
| 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 | ;; | ||
| 34 | ;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. | ||
| 35 | ;; | ||
| 36 | ;; Bug reports, comments, and suggestions are welcome! | ||
| 37 | |||
| 38 | ;; This file contains the portions of the Common Lisp extensions | ||
| 39 | ;; package which should be autoloaded, but need only be present | ||
| 40 | ;; if the compiler or interpreter is used---this file is not | ||
| 41 | ;; necessary for executing compiled code. | ||
| 42 | |||
| 43 | ;; See cl.el for Change Log. | ||
| 44 | |||
| 45 | |||
| 46 | ;; Code: | ||
| 47 | |||
| 48 | (or (memq 'cl-19 features) | ||
| 49 | (error "Tried to load `cl-macs' before `cl'!")) | ||
| 50 | |||
| 51 | |||
| 52 | ;;; We define these here so that this file can compile without having | ||
| 53 | ;;; loaded the cl.el file already. | ||
| 54 | |||
| 55 | (defmacro cl-push (x place) (list 'setq place (list 'cons x place))) | ||
| 56 | (defmacro cl-pop (place) | ||
| 57 | (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) | ||
| 58 | (defmacro cl-pop2 (place) | ||
| 59 | (list 'prog1 (list 'car (list 'cdr place)) | ||
| 60 | (list 'setq place (list 'cdr (list 'cdr place))))) | ||
| 61 | (put 'cl-push 'edebug-form-spec 'edebug-sexps) | ||
| 62 | (put 'cl-pop 'edebug-form-spec 'edebug-sexps) | ||
| 63 | (put 'cl-pop2 'edebug-form-spec 'edebug-sexps) | ||
| 64 | |||
| 65 | (defvar cl-emacs-type) | ||
| 66 | (defvar cl-optimize-safety) | ||
| 67 | (defvar cl-optimize-speed) | ||
| 68 | |||
| 69 | |||
| 70 | ;;; This kludge allows macros which use cl-transform-function-property | ||
| 71 | ;;; to be called at compile-time. | ||
| 72 | |||
| 73 | (require | ||
| 74 | (progn | ||
| 75 | (or (fboundp 'defalias) (fset 'defalias 'fset)) | ||
| 76 | (or (fboundp 'cl-transform-function-property) | ||
| 77 | (defalias 'cl-transform-function-property | ||
| 78 | (function (lambda (n p f) | ||
| 79 | (list 'put (list 'quote n) (list 'quote p) | ||
| 80 | (list 'function (cons 'lambda f))))))) | ||
| 81 | (car (or features (setq features (list 'cl-kludge)))))) | ||
| 82 | |||
| 83 | |||
| 84 | ;;; Initialization. | ||
| 85 | |||
| 86 | (defvar cl-old-bc-file-form nil) | ||
| 87 | |||
| 88 | ;; Patch broken Emacs 18 compiler (re top-level macros). | ||
| 89 | ;; Emacs 19 compiler doesn't need this patch. | ||
| 90 | ;; Also, undo broken definition of `eql' that uses same bytecode as `eq'. | ||
| 91 | (defun cl-compile-time-init () | ||
| 92 | (setq cl-old-bc-file-form (symbol-function 'byte-compile-file-form)) | ||
| 93 | (or (fboundp 'byte-compile-flush-pending) ; Emacs 19 compiler? | ||
| 94 | (defalias 'byte-compile-file-form | ||
| 95 | (function | ||
| 96 | (lambda (form) | ||
| 97 | (setq form (macroexpand form byte-compile-macro-environment)) | ||
| 98 | (if (eq (car-safe form) 'progn) | ||
| 99 | (cons 'progn (mapcar 'byte-compile-file-form (cdr form))) | ||
| 100 | (funcall cl-old-bc-file-form form)))))) | ||
| 101 | (put 'eql 'byte-compile 'cl-byte-compile-compiler-macro) | ||
| 102 | (run-hooks 'cl-hack-bytecomp-hook)) | ||
| 103 | |||
| 104 | |||
| 105 | ;;; Symbols. | ||
| 106 | |||
| 107 | (defvar *gensym-counter*) | ||
| 108 | (defun gensym (&optional arg) | ||
| 109 | "Generate a new uninterned symbol. | ||
| 110 | The name is made by appending a number to PREFIX, default \"G\"." | ||
| 111 | (let ((prefix (if (stringp arg) arg "G")) | ||
| 112 | (num (if (integerp arg) arg | ||
| 113 | (prog1 *gensym-counter* | ||
| 114 | (setq *gensym-counter* (1+ *gensym-counter*)))))) | ||
| 115 | (make-symbol (format "%s%d" prefix num)))) | ||
| 116 | |||
| 117 | (defun gentemp (&optional arg) | ||
| 118 | "Generate a new interned symbol with a unique name. | ||
| 119 | The name is made by appending a number to PREFIX, default \"G\"." | ||
| 120 | (let ((prefix (if (stringp arg) arg "G")) | ||
| 121 | name) | ||
| 122 | (while (intern-soft (setq name (format "%s%d" prefix *gensym-counter*))) | ||
| 123 | (setq *gensym-counter* (1+ *gensym-counter*))) | ||
| 124 | (intern name))) | ||
| 125 | |||
| 126 | |||
| 127 | ;;; Program structure. | ||
| 128 | |||
| 129 | (defmacro defun* (name args &rest body) | ||
| 130 | "(defun* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. | ||
| 131 | Like normal `defun', except ARGLIST allows full Common Lisp conventions, | ||
| 132 | and BODY is implicitly surrounded by (block NAME ...)." | ||
| 133 | (let* ((res (cl-transform-lambda (cons args body) name)) | ||
| 134 | (form (list* 'defun name (cdr res)))) | ||
| 135 | (if (car res) (list 'progn (car res) form) form))) | ||
| 136 | |||
| 137 | (defmacro defmacro* (name args &rest body) | ||
| 138 | "(defmacro* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a macro. | ||
| 139 | Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, | ||
| 140 | and BODY is implicitly surrounded by (block NAME ...)." | ||
| 141 | (let* ((res (cl-transform-lambda (cons args body) name)) | ||
| 142 | (form (list* 'defmacro name (cdr res)))) | ||
| 143 | (if (car res) (list 'progn (car res) form) form))) | ||
| 144 | |||
| 145 | (defmacro function* (func) | ||
| 146 | "(function* SYMBOL-OR-LAMBDA): introduce a function. | ||
| 147 | Like normal `function', except that if argument is a lambda form, its | ||
| 148 | ARGLIST allows full Common Lisp conventions." | ||
| 149 | (if (eq (car-safe func) 'lambda) | ||
| 150 | (let* ((res (cl-transform-lambda (cdr func) 'cl-none)) | ||
| 151 | (form (list 'function (cons 'lambda (cdr res))))) | ||
| 152 | (if (car res) (list 'progn (car res) form) form)) | ||
| 153 | (list 'function func))) | ||
| 154 | |||
| 155 | (defun cl-transform-function-property (func prop form) | ||
| 156 | (let ((res (cl-transform-lambda form func))) | ||
| 157 | (append '(progn) (cdr (cdr (car res))) | ||
| 158 | (list (list 'put (list 'quote func) (list 'quote prop) | ||
| 159 | (list 'function (cons 'lambda (cdr res)))))))) | ||
| 160 | |||
| 161 | (defconst lambda-list-keywords | ||
| 162 | '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) | ||
| 163 | |||
| 164 | (defvar cl-macro-environment nil) | ||
| 165 | (defvar bind-block) (defvar bind-defs) (defvar bind-enquote) | ||
| 166 | (defvar bind-inits) (defvar bind-lets) (defvar bind-forms) | ||
| 167 | |||
| 168 | (defun cl-transform-lambda (form bind-block) | ||
| 169 | (let* ((args (car form)) (body (cdr form)) | ||
| 170 | (bind-defs nil) (bind-enquote nil) | ||
| 171 | (bind-inits nil) (bind-lets nil) (bind-forms nil) | ||
| 172 | (header nil) (simple-args nil)) | ||
| 173 | (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) | ||
| 174 | (cl-push (cl-pop body) header)) | ||
| 175 | (setq args (if (listp args) (copy-list args) (list '&rest args))) | ||
| 176 | (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) | ||
| 177 | (if (setq bind-defs (cadr (memq '&cl-defs args))) | ||
| 178 | (setq args (delq '&cl-defs (delq bind-defs args)) | ||
| 179 | bind-defs (cadr bind-defs))) | ||
| 180 | (if (setq bind-enquote (memq '&cl-quote args)) | ||
| 181 | (setq args (delq '&cl-quote args))) | ||
| 182 | (if (memq '&whole args) (error "&whole not currently implemented")) | ||
| 183 | (let* ((p (memq '&environment args)) (v (cadr p))) | ||
| 184 | (if p (setq args (nconc (delq (car p) (delq v args)) | ||
| 185 | (list '&aux (list v 'cl-macro-environment)))))) | ||
| 186 | (while (and args (symbolp (car args)) | ||
| 187 | (not (memq (car args) '(nil &rest &body &key &aux))) | ||
| 188 | (not (and (eq (car args) '&optional) | ||
| 189 | (or bind-defs (consp (cadr args)))))) | ||
| 190 | (cl-push (cl-pop args) simple-args)) | ||
| 191 | (or (eq bind-block 'cl-none) | ||
| 192 | (setq body (list (list* 'block bind-block body)))) | ||
| 193 | (if (null args) | ||
| 194 | (list* nil (nreverse simple-args) (nconc (nreverse header) body)) | ||
| 195 | (if (memq '&optional simple-args) (cl-push '&optional args)) | ||
| 196 | (cl-do-arglist args nil (- (length simple-args) | ||
| 197 | (if (memq '&optional simple-args) 1 0))) | ||
| 198 | (setq bind-lets (nreverse bind-lets)) | ||
| 199 | (list* (and bind-inits (list* 'eval-when '(compile load eval) | ||
| 200 | (nreverse bind-inits))) | ||
| 201 | (nconc (nreverse simple-args) | ||
| 202 | (list '&rest (car (cl-pop bind-lets)))) | ||
| 203 | (nconc (nreverse header) | ||
| 204 | (list (nconc (list 'let* bind-lets) | ||
| 205 | (nreverse bind-forms) body))))))) | ||
| 206 | |||
| 207 | (defun cl-do-arglist (args expr &optional num) ; uses bind-* | ||
| 208 | (if (nlistp args) | ||
| 209 | (if (or (memq args lambda-list-keywords) (not (symbolp args))) | ||
| 210 | (error "Invalid argument name: %s" args) | ||
| 211 | (cl-push (list args expr) bind-lets)) | ||
| 212 | (setq args (copy-list args)) | ||
| 213 | (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) | ||
| 214 | (let ((p (memq '&body args))) (if p (setcar p '&rest))) | ||
| 215 | (if (memq '&environment args) (error "&environment used incorrectly")) | ||
| 216 | (let ((save-args args) | ||
| 217 | (restarg (memq '&rest args)) | ||
| 218 | (safety (if (cl-compiling-file) cl-optimize-safety 3)) | ||
| 219 | (keys nil) | ||
| 220 | (laterarg nil) (exactarg nil) minarg) | ||
| 221 | (or num (setq num 0)) | ||
| 222 | (if (listp (cadr restarg)) | ||
| 223 | (setq restarg (gensym "--rest--")) | ||
| 224 | (setq restarg (cadr restarg))) | ||
| 225 | (cl-push (list restarg expr) bind-lets) | ||
| 226 | (if (eq (car args) '&whole) | ||
| 227 | (cl-push (list (cl-pop2 args) restarg) bind-lets)) | ||
| 228 | (let ((p args)) | ||
| 229 | (setq minarg restarg) | ||
| 230 | (while (and p (not (memq (car p) lambda-list-keywords))) | ||
| 231 | (or (eq p args) (setq minarg (list 'cdr minarg))) | ||
| 232 | (setq p (cdr p))) | ||
| 233 | (if (memq (car p) '(nil &aux)) | ||
| 234 | (setq minarg (list '= (list 'length restarg) | ||
| 235 | (length (ldiff args p))) | ||
| 236 | exactarg (not (eq args p))))) | ||
| 237 | (while (and args (not (memq (car args) lambda-list-keywords))) | ||
| 238 | (let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car) | ||
| 239 | restarg))) | ||
| 240 | (cl-do-arglist | ||
| 241 | (cl-pop args) | ||
| 242 | (if (or laterarg (= safety 0)) poparg | ||
| 243 | (list 'if minarg poparg | ||
| 244 | (list 'signal '(quote wrong-number-of-arguments) | ||
| 245 | (list 'list (and (not (eq bind-block 'cl-none)) | ||
| 246 | (list 'quote bind-block)) | ||
| 247 | (list 'length restarg))))))) | ||
| 248 | (setq num (1+ num) laterarg t)) | ||
| 249 | (while (and (eq (car args) '&optional) (cl-pop args)) | ||
| 250 | (while (and args (not (memq (car args) lambda-list-keywords))) | ||
| 251 | (let ((arg (cl-pop args))) | ||
| 252 | (or (consp arg) (setq arg (list arg))) | ||
| 253 | (if (cddr arg) (cl-do-arglist (nth 2 arg) (list 'and restarg t))) | ||
| 254 | (let ((def (if (cdr arg) (nth 1 arg) | ||
| 255 | (or (car bind-defs) | ||
| 256 | (nth 1 (assq (car arg) bind-defs))))) | ||
| 257 | (poparg (list 'pop restarg))) | ||
| 258 | (and def bind-enquote (setq def (list 'quote def))) | ||
| 259 | (cl-do-arglist (car arg) | ||
| 260 | (if def (list 'if restarg poparg def) poparg)) | ||
| 261 | (setq num (1+ num)))))) | ||
| 262 | (if (eq (car args) '&rest) | ||
| 263 | (let ((arg (cl-pop2 args))) | ||
| 264 | (if (consp arg) (cl-do-arglist arg restarg))) | ||
| 265 | (or (eq (car args) '&key) (= safety 0) exactarg | ||
| 266 | (cl-push (list 'if restarg | ||
| 267 | (list 'signal '(quote wrong-number-of-arguments) | ||
| 268 | (list 'list | ||
| 269 | (and (not (eq bind-block 'cl-none)) | ||
| 270 | (list 'quote bind-block)) | ||
| 271 | (list '+ num (list 'length restarg))))) | ||
| 272 | bind-forms))) | ||
| 273 | (while (and (eq (car args) '&key) (cl-pop args)) | ||
| 274 | (while (and args (not (memq (car args) lambda-list-keywords))) | ||
| 275 | (let ((arg (cl-pop args))) | ||
| 276 | (or (consp arg) (setq arg (list arg))) | ||
| 277 | (let* ((karg (if (consp (car arg)) (caar arg) | ||
| 278 | (intern (format ":%s" (car arg))))) | ||
| 279 | (varg (if (consp (car arg)) (cadar arg) (car arg))) | ||
| 280 | (def (if (cdr arg) (cadr arg) | ||
| 281 | (or (car bind-defs) (cadr (assq varg bind-defs))))) | ||
| 282 | (look (list 'memq (list 'quote karg) restarg))) | ||
| 283 | (and def bind-enquote (setq def (list 'quote def))) | ||
| 284 | (if (cddr arg) | ||
| 285 | (let* ((temp (or (nth 2 arg) (gensym))) | ||
| 286 | (val (list 'car (list 'cdr temp)))) | ||
| 287 | (cl-do-arglist temp look) | ||
| 288 | (cl-do-arglist varg | ||
| 289 | (list 'if temp | ||
| 290 | (list 'prog1 val (list 'setq temp t)) | ||
| 291 | def))) | ||
| 292 | (cl-do-arglist | ||
| 293 | varg | ||
| 294 | (list 'car | ||
| 295 | (list 'cdr | ||
| 296 | (if (null def) | ||
| 297 | look | ||
| 298 | (list 'or look | ||
| 299 | (if (eq (cl-const-expr-p def) t) | ||
| 300 | (list | ||
| 301 | 'quote | ||
| 302 | (list nil (cl-const-expr-val def))) | ||
| 303 | (list 'list nil def)))))))) | ||
| 304 | (cl-push karg keys) | ||
| 305 | (if (= (aref (symbol-name karg) 0) ?:) | ||
| 306 | (progn (set karg karg) | ||
| 307 | (cl-push (list 'setq karg (list 'quote karg)) | ||
| 308 | bind-inits))))))) | ||
| 309 | (setq keys (nreverse keys)) | ||
| 310 | (or (and (eq (car args) '&allow-other-keys) (cl-pop args)) | ||
| 311 | (null keys) (= safety 0) | ||
| 312 | (let* ((var (gensym "--keys--")) | ||
| 313 | (allow '(:allow-other-keys)) | ||
| 314 | (check (list | ||
| 315 | 'while var | ||
| 316 | (list | ||
| 317 | 'cond | ||
| 318 | (list (list 'memq (list 'car var) | ||
| 319 | (list 'quote (append keys allow))) | ||
| 320 | (list 'setq var (list 'cdr (list 'cdr var)))) | ||
| 321 | (list (list 'car | ||
| 322 | (list 'cdr | ||
| 323 | (list 'memq (cons 'quote allow) | ||
| 324 | restarg))) | ||
| 325 | (list 'setq var nil)) | ||
| 326 | (list t | ||
| 327 | (list | ||
| 328 | 'error | ||
| 329 | (format "Keyword argument %%s not one of %s" | ||
| 330 | keys) | ||
| 331 | (list 'car var))))))) | ||
| 332 | (cl-push (list 'let (list (list var restarg)) check) bind-forms))) | ||
| 333 | (while (and (eq (car args) '&aux) (cl-pop args)) | ||
| 334 | (while (and args (not (memq (car args) lambda-list-keywords))) | ||
| 335 | (if (consp (car args)) | ||
| 336 | (if (and bind-enquote (cadar args)) | ||
| 337 | (cl-do-arglist (caar args) | ||
| 338 | (list 'quote (cadr (cl-pop args)))) | ||
| 339 | (cl-do-arglist (caar args) (cadr (cl-pop args)))) | ||
| 340 | (cl-do-arglist (cl-pop args) nil)))) | ||
| 341 | (if args (error "Malformed argument list %s" save-args))))) | ||
| 342 | |||
| 343 | (defun cl-arglist-args (args) | ||
| 344 | (if (nlistp args) (list args) | ||
| 345 | (let ((res nil) (kind nil) arg) | ||
| 346 | (while (consp args) | ||
| 347 | (setq arg (cl-pop args)) | ||
| 348 | (if (memq arg lambda-list-keywords) (setq kind arg) | ||
| 349 | (if (eq arg '&cl-defs) (cl-pop args) | ||
| 350 | (and (consp arg) kind (setq arg (car arg))) | ||
| 351 | (and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg))) | ||
| 352 | (setq res (nconc res (cl-arglist-args arg)))))) | ||
| 353 | (nconc res (and args (list args)))))) | ||
| 354 | |||
| 355 | (defmacro destructuring-bind (args expr &rest body) | ||
| 356 | (let* ((bind-lets nil) (bind-forms nil) (bind-inits nil) | ||
| 357 | (bind-defs nil) (bind-block 'cl-none)) | ||
| 358 | (cl-do-arglist (or args '(&aux)) expr) | ||
| 359 | (append '(progn) bind-inits | ||
| 360 | (list (nconc (list 'let* (nreverse bind-lets)) | ||
| 361 | (nreverse bind-forms) body))))) | ||
| 362 | |||
| 363 | |||
| 364 | ;;; The `eval-when' form. | ||
| 365 | |||
| 366 | (defvar cl-not-toplevel nil) | ||
| 367 | |||
| 368 | (defmacro eval-when (when &rest body) | ||
| 369 | "(eval-when (WHEN...) BODY...): control when BODY is evaluated. | ||
| 370 | If `compile' is in WHEN, BODY is evaluated when compiled at top-level. | ||
| 371 | If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. | ||
| 372 | If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level." | ||
| 373 | (if (and (fboundp 'cl-compiling-file) (cl-compiling-file) | ||
| 374 | (not cl-not-toplevel) (not (boundp 'for-effect))) ; horrible kludge | ||
| 375 | (let ((comp (or (memq 'compile when) (memq ':compile-toplevel when))) | ||
| 376 | (cl-not-toplevel t)) | ||
| 377 | (if (or (memq 'load when) (memq ':load-toplevel when)) | ||
| 378 | (if comp (cons 'progn (mapcar 'cl-compile-time-too body)) | ||
| 379 | (list* 'if nil nil body)) | ||
| 380 | (progn (if comp (eval (cons 'progn body))) nil))) | ||
| 381 | (and (or (memq 'eval when) (memq ':execute when)) | ||
| 382 | (cons 'progn body)))) | ||
| 383 | |||
| 384 | (defun cl-compile-time-too (form) | ||
| 385 | (or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler)) | ||
| 386 | (setq form (macroexpand | ||
| 387 | form (cons '(eval-when) byte-compile-macro-environment)))) | ||
| 388 | (cond ((eq (car-safe form) 'progn) | ||
| 389 | (cons 'progn (mapcar 'cl-compile-time-too (cdr form)))) | ||
| 390 | ((eq (car-safe form) 'eval-when) | ||
| 391 | (let ((when (nth 1 form))) | ||
| 392 | (if (or (memq 'eval when) (memq ':execute when)) | ||
| 393 | (list* 'eval-when (cons 'compile when) (cddr form)) | ||
| 394 | form))) | ||
| 395 | (t (eval form) form))) | ||
| 396 | |||
| 397 | (or (and (fboundp 'eval-when-compile) | ||
| 398 | (not (eq (car-safe (symbol-function 'eval-when-compile)) 'autoload))) | ||
| 399 | (eval '(defmacro eval-when-compile (&rest body) | ||
| 400 | "Like `progn', but evaluates the body at compile time. | ||
| 401 | The result of the body appears to the compiler as a quoted constant." | ||
| 402 | (list 'quote (eval (cons 'progn body)))))) | ||
| 403 | |||
| 404 | (defmacro load-time-value (form &optional read-only) | ||
| 405 | "Like `progn', but evaluates the body at load time. | ||
| 406 | The result of the body appears to the compiler as a quoted constant." | ||
| 407 | (if (cl-compiling-file) | ||
| 408 | (let* ((temp (gentemp "--cl-load-time--")) | ||
| 409 | (set (list 'set (list 'quote temp) form))) | ||
| 410 | (if (and (fboundp 'byte-compile-file-form-defmumble) | ||
| 411 | (boundp 'this-kind) (boundp 'that-one)) | ||
| 412 | (fset 'byte-compile-file-form | ||
| 413 | (list 'lambda '(form) | ||
| 414 | (list 'fset '(quote byte-compile-file-form) | ||
| 415 | (list 'quote | ||
| 416 | (symbol-function 'byte-compile-file-form))) | ||
| 417 | (list 'byte-compile-file-form (list 'quote set)) | ||
| 418 | '(byte-compile-file-form form))) | ||
| 419 | (print set (symbol-value 'outbuffer))) | ||
| 420 | (list 'symbol-value (list 'quote temp))) | ||
| 421 | (list 'quote (eval form)))) | ||
| 422 | |||
| 423 | |||
| 424 | ;;; Conditional control structures. | ||
| 425 | |||
| 426 | (defmacro case (expr &rest clauses) | ||
| 427 | "(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. | ||
| 428 | Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared | ||
| 429 | against each key in each KEYLIST; the corresponding BODY is evaluated. | ||
| 430 | If no clause succeeds, case returns nil. A single atom may be used in | ||
| 431 | place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is | ||
| 432 | allowed only in the final clause, and matches if no other keys match. | ||
| 433 | Key values are compared by `eql'." | ||
| 434 | (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) | ||
| 435 | (head-list nil) | ||
| 436 | (body (cons | ||
| 437 | 'cond | ||
| 438 | (mapcar | ||
| 439 | (function | ||
| 440 | (lambda (c) | ||
| 441 | (cons (cond ((memq (car c) '(t otherwise)) t) | ||
| 442 | ((eq (car c) 'ecase-error-flag) | ||
| 443 | (list 'error "ecase failed: %s, %s" | ||
| 444 | temp (list 'quote (reverse head-list)))) | ||
| 445 | ((listp (car c)) | ||
| 446 | (setq head-list (append (car c) head-list)) | ||
| 447 | (list 'member* temp (list 'quote (car c)))) | ||
| 448 | (t | ||
| 449 | (if (memq (car c) head-list) | ||
| 450 | (error "Duplicate key in case: %s" | ||
| 451 | (car c))) | ||
| 452 | (cl-push (car c) head-list) | ||
| 453 | (list 'eql temp (list 'quote (car c))))) | ||
| 454 | (or (cdr c) '(nil))))) | ||
| 455 | clauses)))) | ||
| 456 | (if (eq temp expr) body | ||
| 457 | (list 'let (list (list temp expr)) body)))) | ||
| 458 | |||
| 459 | (defmacro ecase (expr &rest clauses) | ||
| 460 | "(ecase EXPR CLAUSES...): like `case', but error if no case fits. | ||
| 461 | `otherwise'-clauses are not allowed." | ||
| 462 | (list* 'case expr (append clauses '((ecase-error-flag))))) | ||
| 463 | |||
| 464 | (defmacro typecase (expr &rest clauses) | ||
| 465 | "(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. | ||
| 466 | Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it | ||
| 467 | satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, | ||
| 468 | typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the | ||
| 469 | final clause, and matches if no other keys match." | ||
| 470 | (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) | ||
| 471 | (type-list nil) | ||
| 472 | (body (cons | ||
| 473 | 'cond | ||
| 474 | (mapcar | ||
| 475 | (function | ||
| 476 | (lambda (c) | ||
| 477 | (cons (cond ((eq (car c) 'otherwise) t) | ||
| 478 | ((eq (car c) 'ecase-error-flag) | ||
| 479 | (list 'error "etypecase failed: %s, %s" | ||
| 480 | temp (list 'quote (reverse type-list)))) | ||
| 481 | (t | ||
| 482 | (cl-push (car c) type-list) | ||
| 483 | (cl-make-type-test temp (car c)))) | ||
| 484 | (or (cdr c) '(nil))))) | ||
| 485 | clauses)))) | ||
| 486 | (if (eq temp expr) body | ||
| 487 | (list 'let (list (list temp expr)) body)))) | ||
| 488 | |||
| 489 | (defmacro etypecase (expr &rest clauses) | ||
| 490 | "(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. | ||
| 491 | `otherwise'-clauses are not allowed." | ||
| 492 | (list* 'typecase expr (append clauses '((ecase-error-flag))))) | ||
| 493 | |||
| 494 | |||
| 495 | ;;; Blocks and exits. | ||
| 496 | |||
| 497 | (defmacro block (name &rest body) | ||
| 498 | "(block NAME BODY...): define a lexically-scoped block named NAME. | ||
| 499 | NAME may be any symbol. Code inside the BODY forms can call `return-from' | ||
| 500 | to jump prematurely out of the block. This differs from `catch' and `throw' | ||
| 501 | in two respects: First, the NAME is an unevaluated symbol rather than a | ||
| 502 | quoted symbol or other form; and second, NAME is lexically rather than | ||
| 503 | dynamically scoped: Only references to it within BODY will work. These | ||
| 504 | references may appear inside macro expansions, but not inside functions | ||
| 505 | called from BODY." | ||
| 506 | (if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body) | ||
| 507 | (list 'cl-block-wrapper | ||
| 508 | (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) | ||
| 509 | body)))) | ||
| 510 | |||
| 511 | (defvar cl-active-block-names nil) | ||
| 512 | |||
| 513 | (put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block) | ||
| 514 | (defun cl-byte-compile-block (cl-form) | ||
| 515 | (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing compiler | ||
| 516 | (progn | ||
| 517 | (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) | ||
| 518 | (cl-active-block-names (cons cl-entry cl-active-block-names)) | ||
| 519 | (cl-body (byte-compile-top-level | ||
| 520 | (cons 'progn (cddr (nth 1 cl-form)))))) | ||
| 521 | (if (cdr cl-entry) | ||
| 522 | (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body)) | ||
| 523 | (byte-compile-form cl-body)))) | ||
| 524 | (byte-compile-form (nth 1 cl-form)))) | ||
| 525 | |||
| 526 | (put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw) | ||
| 527 | (defun cl-byte-compile-throw (cl-form) | ||
| 528 | (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) | ||
| 529 | (if cl-found (setcdr cl-found t))) | ||
| 530 | (byte-compile-normal-call (cons 'throw (cdr cl-form)))) | ||
| 531 | |||
| 532 | (defmacro return (&optional res) | ||
| 533 | "(return [RESULT]): return from the block named nil. | ||
| 534 | This is equivalent to `(return-from nil RESULT)'." | ||
| 535 | (list 'return-from nil res)) | ||
| 536 | |||
| 537 | (defmacro return-from (name &optional res) | ||
| 538 | "(return-from NAME [RESULT]): return from the block named NAME. | ||
| 539 | This jump out to the innermost enclosing `(block NAME ...)' form, | ||
| 540 | returning RESULT from that form (or nil if RESULT is omitted). | ||
| 541 | This is compatible with Common Lisp, but note that `defun' and | ||
| 542 | `defmacro' do not create implicit blocks as they do in Common Lisp." | ||
| 543 | (let ((name2 (intern (format "--cl-block-%s--" name)))) | ||
| 544 | (list 'cl-block-throw (list 'quote name2) res))) | ||
| 545 | |||
| 546 | |||
| 547 | ;;; The "loop" macro. | ||
| 548 | |||
| 549 | (defvar args) (defvar loop-accum-var) (defvar loop-accum-vars) | ||
| 550 | (defvar loop-bindings) (defvar loop-body) (defvar loop-destr-temps) | ||
| 551 | (defvar loop-finally) (defvar loop-finish-flag) (defvar loop-first-flag) | ||
| 552 | (defvar loop-initially) (defvar loop-map-form) (defvar loop-name) | ||
| 553 | (defvar loop-result) (defvar loop-result-explicit) | ||
| 554 | (defvar loop-result-var) (defvar loop-steps) (defvar loop-symbol-macs) | ||
| 555 | |||
| 556 | (defmacro loop (&rest args) | ||
| 557 | "(loop CLAUSE...): The Common Lisp `loop' macro. | ||
| 558 | Valid clauses are: | ||
| 559 | for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, | ||
| 560 | for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, | ||
| 561 | for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, | ||
| 562 | always COND, never COND, thereis COND, collect EXPR into VAR, | ||
| 563 | append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, | ||
| 564 | count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, | ||
| 565 | if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], | ||
| 566 | unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], | ||
| 567 | do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, | ||
| 568 | finally return EXPR, named NAME." | ||
| 569 | (if (not (memq t (mapcar 'symbolp (delq nil (delq t (copy-list args)))))) | ||
| 570 | (list 'block nil (list* 'while t args)) | ||
| 571 | (let ((loop-name nil) (loop-bindings nil) | ||
| 572 | (loop-body nil) (loop-steps nil) | ||
| 573 | (loop-result nil) (loop-result-explicit nil) | ||
| 574 | (loop-result-var nil) (loop-finish-flag nil) | ||
| 575 | (loop-accum-var nil) (loop-accum-vars nil) | ||
| 576 | (loop-initially nil) (loop-finally nil) | ||
| 577 | (loop-map-form nil) (loop-first-flag nil) | ||
| 578 | (loop-destr-temps nil) (loop-symbol-macs nil)) | ||
| 579 | (setq args (append args '(cl-end-loop))) | ||
| 580 | (while (not (eq (car args) 'cl-end-loop)) (cl-parse-loop-clause)) | ||
| 581 | (if loop-finish-flag | ||
| 582 | (cl-push (list (list loop-finish-flag t)) loop-bindings)) | ||
| 583 | (if loop-first-flag | ||
| 584 | (progn (cl-push (list (list loop-first-flag t)) loop-bindings) | ||
| 585 | (cl-push (list 'setq loop-first-flag nil) loop-steps))) | ||
| 586 | (let* ((epilogue (nconc (nreverse loop-finally) | ||
| 587 | (list (or loop-result-explicit loop-result)))) | ||
| 588 | (ands (cl-loop-build-ands (nreverse loop-body))) | ||
| 589 | (while-body (nconc (cadr ands) (nreverse loop-steps))) | ||
| 590 | (body (append | ||
| 591 | (nreverse loop-initially) | ||
| 592 | (list (if loop-map-form | ||
| 593 | (list 'block '--cl-finish-- | ||
| 594 | (subst | ||
| 595 | (if (eq (car ands) t) while-body | ||
| 596 | (cons (list 'or (car ands) | ||
| 597 | '(return-from --cl-finish-- | ||
| 598 | nil)) | ||
| 599 | while-body)) | ||
| 600 | '--cl-map loop-map-form)) | ||
| 601 | (list* 'while (car ands) while-body))) | ||
| 602 | (if loop-finish-flag | ||
| 603 | (if (equal epilogue '(nil)) (list loop-result-var) | ||
| 604 | (list (list 'if loop-finish-flag | ||
| 605 | (cons 'progn epilogue) loop-result-var))) | ||
| 606 | epilogue)))) | ||
| 607 | (if loop-result-var (cl-push (list loop-result-var) loop-bindings)) | ||
| 608 | (while loop-bindings | ||
| 609 | (if (cdar loop-bindings) | ||
| 610 | (setq body (list (cl-loop-let (cl-pop loop-bindings) body t))) | ||
| 611 | (let ((lets nil)) | ||
| 612 | (while (and loop-bindings | ||
| 613 | (not (cdar loop-bindings))) | ||
| 614 | (cl-push (car (cl-pop loop-bindings)) lets)) | ||
| 615 | (setq body (list (cl-loop-let lets body nil)))))) | ||
| 616 | (if loop-symbol-macs | ||
| 617 | (setq body (list (list* 'symbol-macrolet loop-symbol-macs body)))) | ||
| 618 | (list* 'block loop-name body))))) | ||
| 619 | |||
| 620 | (defun cl-parse-loop-clause () ; uses args, loop-* | ||
| 621 | (let ((word (cl-pop args)) | ||
| 622 | (hash-types '(hash-key hash-keys hash-value hash-values)) | ||
| 623 | (key-types '(key-code key-codes key-seq key-seqs | ||
| 624 | key-binding key-bindings))) | ||
| 625 | (cond | ||
| 626 | |||
| 627 | ((null args) | ||
| 628 | (error "Malformed `loop' macro")) | ||
| 629 | |||
| 630 | ((eq word 'named) | ||
| 631 | (setq loop-name (cl-pop args))) | ||
| 632 | |||
| 633 | ((eq word 'initially) | ||
| 634 | (if (memq (car args) '(do doing)) (cl-pop args)) | ||
| 635 | (or (consp (car args)) (error "Syntax error on `initially' clause")) | ||
| 636 | (while (consp (car args)) | ||
| 637 | (cl-push (cl-pop args) loop-initially))) | ||
| 638 | |||
| 639 | ((eq word 'finally) | ||
| 640 | (if (eq (car args) 'return) | ||
| 641 | (setq loop-result-explicit (or (cl-pop2 args) '(quote nil))) | ||
| 642 | (if (memq (car args) '(do doing)) (cl-pop args)) | ||
| 643 | (or (consp (car args)) (error "Syntax error on `finally' clause")) | ||
| 644 | (if (and (eq (caar args) 'return) (null loop-name)) | ||
| 645 | (setq loop-result-explicit (or (nth 1 (cl-pop args)) '(quote nil))) | ||
| 646 | (while (consp (car args)) | ||
| 647 | (cl-push (cl-pop args) loop-finally))))) | ||
| 648 | |||
| 649 | ((memq word '(for as)) | ||
| 650 | (let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil) | ||
| 651 | (ands nil)) | ||
| 652 | (while | ||
| 653 | (let ((var (or (cl-pop args) (gensym)))) | ||
| 654 | (setq word (cl-pop args)) | ||
| 655 | (if (eq word 'being) (setq word (cl-pop args))) | ||
| 656 | (if (memq word '(the each)) (setq word (cl-pop args))) | ||
| 657 | (if (memq word '(buffer buffers)) | ||
| 658 | (setq word 'in args (cons '(buffer-list) args))) | ||
| 659 | (cond | ||
| 660 | |||
| 661 | ((memq word '(from downfrom upfrom to downto upto | ||
| 662 | above below by)) | ||
| 663 | (cl-push word args) | ||
| 664 | (if (memq (car args) '(downto above)) | ||
| 665 | (error "Must specify `from' value for downward loop")) | ||
| 666 | (let* ((down (or (eq (car args) 'downfrom) | ||
| 667 | (memq (caddr args) '(downto above)))) | ||
| 668 | (excl (or (memq (car args) '(above below)) | ||
| 669 | (memq (caddr args) '(above below)))) | ||
| 670 | (start (and (memq (car args) '(from upfrom downfrom)) | ||
| 671 | (cl-pop2 args))) | ||
| 672 | (end (and (memq (car args) | ||
| 673 | '(to upto downto above below)) | ||
| 674 | (cl-pop2 args))) | ||
| 675 | (step (and (eq (car args) 'by) (cl-pop2 args))) | ||
| 676 | (end-var (and (not (cl-const-expr-p end)) (gensym))) | ||
| 677 | (step-var (and (not (cl-const-expr-p step)) | ||
| 678 | (gensym)))) | ||
| 679 | (and step (numberp step) (<= step 0) | ||
| 680 | (error "Loop `by' value is not positive: %s" step)) | ||
| 681 | (cl-push (list var (or start 0)) loop-for-bindings) | ||
| 682 | (if end-var (cl-push (list end-var end) loop-for-bindings)) | ||
| 683 | (if step-var (cl-push (list step-var step) | ||
| 684 | loop-for-bindings)) | ||
| 685 | (if end | ||
| 686 | (cl-push (list | ||
| 687 | (if down (if excl '> '>=) (if excl '< '<=)) | ||
| 688 | var (or end-var end)) loop-body)) | ||
| 689 | (cl-push (list var (list (if down '- '+) var | ||
| 690 | (or step-var step 1))) | ||
| 691 | loop-for-steps))) | ||
| 692 | |||
| 693 | ((memq word '(in in-ref on)) | ||
| 694 | (let* ((on (eq word 'on)) | ||
| 695 | (temp (if (and on (symbolp var)) var (gensym)))) | ||
| 696 | (cl-push (list temp (cl-pop args)) loop-for-bindings) | ||
| 697 | (cl-push (list 'consp temp) loop-body) | ||
| 698 | (if (eq word 'in-ref) | ||
| 699 | (cl-push (list var (list 'car temp)) loop-symbol-macs) | ||
| 700 | (or (eq temp var) | ||
| 701 | (progn | ||
| 702 | (cl-push (list var nil) loop-for-bindings) | ||
| 703 | (cl-push (list var (if on temp (list 'car temp))) | ||
| 704 | loop-for-sets)))) | ||
| 705 | (cl-push (list temp | ||
| 706 | (if (eq (car args) 'by) | ||
| 707 | (let ((step (cl-pop2 args))) | ||
| 708 | (if (and (memq (car-safe step) | ||
| 709 | '(quote function | ||
| 710 | function*)) | ||
| 711 | (symbolp (nth 1 step))) | ||
| 712 | (list (nth 1 step) temp) | ||
| 713 | (list 'funcall step temp))) | ||
| 714 | (list 'cdr temp))) | ||
| 715 | loop-for-steps))) | ||
| 716 | |||
| 717 | ((eq word '=) | ||
| 718 | (let* ((start (cl-pop args)) | ||
| 719 | (then (if (eq (car args) 'then) (cl-pop2 args) start))) | ||
| 720 | (cl-push (list var nil) loop-for-bindings) | ||
| 721 | (if (or ands (eq (car args) 'and)) | ||
| 722 | (progn | ||
| 723 | (cl-push (list var | ||
| 724 | (list 'if | ||
| 725 | (or loop-first-flag | ||
| 726 | (setq loop-first-flag | ||
| 727 | (gensym))) | ||
| 728 | start var)) | ||
| 729 | loop-for-sets) | ||
| 730 | (cl-push (list var then) loop-for-steps)) | ||
| 731 | (cl-push (list var | ||
| 732 | (if (eq start then) start | ||
| 733 | (list 'if | ||
| 734 | (or loop-first-flag | ||
| 735 | (setq loop-first-flag (gensym))) | ||
| 736 | start then))) | ||
| 737 | loop-for-sets)))) | ||
| 738 | |||
| 739 | ((memq word '(across across-ref)) | ||
| 740 | (let ((temp-vec (gensym)) (temp-idx (gensym))) | ||
| 741 | (cl-push (list temp-vec (cl-pop args)) loop-for-bindings) | ||
| 742 | (cl-push (list temp-idx -1) loop-for-bindings) | ||
| 743 | (cl-push (list '< (list 'setq temp-idx (list '1+ temp-idx)) | ||
| 744 | (list 'length temp-vec)) loop-body) | ||
| 745 | (if (eq word 'across-ref) | ||
| 746 | (cl-push (list var (list 'aref temp-vec temp-idx)) | ||
| 747 | loop-symbol-macs) | ||
| 748 | (cl-push (list var nil) loop-for-bindings) | ||
| 749 | (cl-push (list var (list 'aref temp-vec temp-idx)) | ||
| 750 | loop-for-sets)))) | ||
| 751 | |||
| 752 | ((memq word '(element elements)) | ||
| 753 | (let ((ref (or (memq (car args) '(in-ref of-ref)) | ||
| 754 | (and (not (memq (car args) '(in of))) | ||
| 755 | (error "Expected `of'")))) | ||
| 756 | (seq (cl-pop2 args)) | ||
| 757 | (temp-seq (gensym)) | ||
| 758 | (temp-idx (if (eq (car args) 'using) | ||
| 759 | (if (and (= (length (cadr args)) 2) | ||
| 760 | (eq (caadr args) 'index)) | ||
| 761 | (cadr (cl-pop2 args)) | ||
| 762 | (error "Bad `using' clause")) | ||
| 763 | (gensym)))) | ||
| 764 | (cl-push (list temp-seq seq) loop-for-bindings) | ||
| 765 | (cl-push (list temp-idx 0) loop-for-bindings) | ||
| 766 | (if ref | ||
| 767 | (let ((temp-len (gensym))) | ||
| 768 | (cl-push (list temp-len (list 'length temp-seq)) | ||
| 769 | loop-for-bindings) | ||
| 770 | (cl-push (list var (list 'elt temp-seq temp-idx)) | ||
| 771 | loop-symbol-macs) | ||
| 772 | (cl-push (list '< temp-idx temp-len) loop-body)) | ||
| 773 | (cl-push (list var nil) loop-for-bindings) | ||
| 774 | (cl-push (list 'and temp-seq | ||
| 775 | (list 'or (list 'consp temp-seq) | ||
| 776 | (list '< temp-idx | ||
| 777 | (list 'length temp-seq)))) | ||
| 778 | loop-body) | ||
| 779 | (cl-push (list var (list 'if (list 'consp temp-seq) | ||
| 780 | (list 'pop temp-seq) | ||
| 781 | (list 'aref temp-seq temp-idx))) | ||
| 782 | loop-for-sets)) | ||
| 783 | (cl-push (list temp-idx (list '1+ temp-idx)) | ||
| 784 | loop-for-steps))) | ||
| 785 | |||
| 786 | ((memq word hash-types) | ||
| 787 | (or (memq (car args) '(in of)) (error "Expected `of'")) | ||
| 788 | (let* ((table (cl-pop2 args)) | ||
| 789 | (other (if (eq (car args) 'using) | ||
| 790 | (if (and (= (length (cadr args)) 2) | ||
| 791 | (memq (caadr args) hash-types) | ||
| 792 | (not (eq (caadr args) word))) | ||
| 793 | (cadr (cl-pop2 args)) | ||
| 794 | (error "Bad `using' clause")) | ||
| 795 | (gensym)))) | ||
| 796 | (if (memq word '(hash-value hash-values)) | ||
| 797 | (setq var (prog1 other (setq other var)))) | ||
| 798 | (setq loop-map-form | ||
| 799 | (list 'maphash (list 'function | ||
| 800 | (list* 'lambda (list var other) | ||
| 801 | '--cl-map)) table)))) | ||
| 802 | |||
| 803 | ((memq word '(symbol present-symbol external-symbol | ||
| 804 | symbols present-symbols external-symbols)) | ||
| 805 | (let ((ob (and (memq (car args) '(in of)) (cl-pop2 args)))) | ||
| 806 | (setq loop-map-form | ||
| 807 | (list 'mapatoms (list 'function | ||
| 808 | (list* 'lambda (list var) | ||
| 809 | '--cl-map)) ob)))) | ||
| 810 | |||
| 811 | ((memq word '(overlay overlays extent extents)) | ||
| 812 | (let ((buf nil) (from nil) (to nil)) | ||
| 813 | (while (memq (car args) '(in of from to)) | ||
| 814 | (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) | ||
| 815 | ((eq (car args) 'to) (setq to (cl-pop2 args))) | ||
| 816 | (t (setq buf (cl-pop2 args))))) | ||
| 817 | (setq loop-map-form | ||
| 818 | (list 'cl-map-extents | ||
| 819 | (list 'function (list 'lambda (list var (gensym)) | ||
| 820 | '(progn . --cl-map) nil)) | ||
| 821 | buf from to)))) | ||
| 822 | |||
| 823 | ((memq word '(interval intervals)) | ||
| 824 | (let ((buf nil) (prop nil) (from nil) (to nil) | ||
| 825 | (var1 (gensym)) (var2 (gensym))) | ||
| 826 | (while (memq (car args) '(in of property from to)) | ||
| 827 | (cond ((eq (car args) 'from) (setq from (cl-pop2 args))) | ||
| 828 | ((eq (car args) 'to) (setq to (cl-pop2 args))) | ||
| 829 | ((eq (car args) 'property) | ||
| 830 | (setq prop (cl-pop2 args))) | ||
| 831 | (t (setq buf (cl-pop2 args))))) | ||
| 832 | (if (and (consp var) (symbolp (car var)) (symbolp (cdr var))) | ||
| 833 | (setq var1 (car var) var2 (cdr var)) | ||
| 834 | (cl-push (list var (list 'cons var1 var2)) loop-for-sets)) | ||
| 835 | (setq loop-map-form | ||
| 836 | (list 'cl-map-intervals | ||
| 837 | (list 'function (list 'lambda (list var1 var2) | ||
| 838 | '(progn . --cl-map))) | ||
| 839 | buf prop from to)))) | ||
| 840 | |||
| 841 | ((memq word key-types) | ||
| 842 | (or (memq (car args) '(in of)) (error "Expected `of'")) | ||
| 843 | (let ((map (cl-pop2 args)) | ||
| 844 | (other (if (eq (car args) 'using) | ||
| 845 | (if (and (= (length (cadr args)) 2) | ||
| 846 | (memq (caadr args) key-types) | ||
| 847 | (not (eq (caadr args) word))) | ||
| 848 | (cadr (cl-pop2 args)) | ||
| 849 | (error "Bad `using' clause")) | ||
| 850 | (gensym)))) | ||
| 851 | (if (memq word '(key-binding key-bindings)) | ||
| 852 | (setq var (prog1 other (setq other var)))) | ||
| 853 | (setq loop-map-form | ||
| 854 | (list (if (memq word '(key-seq key-seqs)) | ||
| 855 | 'cl-map-keymap-recursively 'cl-map-keymap) | ||
| 856 | (list 'function (list* 'lambda (list var other) | ||
| 857 | '--cl-map)) map)))) | ||
| 858 | |||
| 859 | ((memq word '(frame frames screen screens)) | ||
| 860 | (let ((temp (gensym))) | ||
| 861 | (cl-push (list var (if (eq cl-emacs-type 'lucid) | ||
| 862 | '(selected-screen) '(selected-frame))) | ||
| 863 | loop-for-bindings) | ||
| 864 | (cl-push (list temp nil) loop-for-bindings) | ||
| 865 | (cl-push (list 'prog1 (list 'not (list 'eq var temp)) | ||
| 866 | (list 'or temp (list 'setq temp var))) | ||
| 867 | loop-body) | ||
| 868 | (cl-push (list var (list (if (eq cl-emacs-type 'lucid) | ||
| 869 | 'next-screen 'next-frame) var)) | ||
| 870 | loop-for-steps))) | ||
| 871 | |||
| 872 | ((memq word '(window windows)) | ||
| 873 | (let ((scr (and (memq (car args) '(in of)) (cl-pop2 args))) | ||
| 874 | (temp (gensym))) | ||
| 875 | (cl-push (list var (if scr | ||
| 876 | (list (if (eq cl-emacs-type 'lucid) | ||
| 877 | 'screen-selected-window | ||
| 878 | 'frame-selected-window) scr) | ||
| 879 | '(selected-window))) | ||
| 880 | loop-for-bindings) | ||
| 881 | (cl-push (list temp nil) loop-for-bindings) | ||
| 882 | (cl-push (list 'prog1 (list 'not (list 'eq var temp)) | ||
| 883 | (list 'or temp (list 'setq temp var))) | ||
| 884 | loop-body) | ||
| 885 | (cl-push (list var (list 'next-window var)) loop-for-steps))) | ||
| 886 | |||
| 887 | (t | ||
| 888 | (let ((handler (and (symbolp word) | ||
| 889 | (get word 'cl-loop-for-handler)))) | ||
| 890 | (if handler | ||
| 891 | (funcall handler var) | ||
| 892 | (error "Expected a `for' preposition, found %s" word))))) | ||
| 893 | (eq (car args) 'and)) | ||
| 894 | (setq ands t) | ||
| 895 | (cl-pop args)) | ||
| 896 | (if (and ands loop-for-bindings) | ||
| 897 | (cl-push (nreverse loop-for-bindings) loop-bindings) | ||
| 898 | (setq loop-bindings (nconc (mapcar 'list loop-for-bindings) | ||
| 899 | loop-bindings))) | ||
| 900 | (if loop-for-sets | ||
| 901 | (cl-push (list 'progn | ||
| 902 | (cl-loop-let (nreverse loop-for-sets) 'setq ands) | ||
| 903 | t) loop-body)) | ||
| 904 | (if loop-for-steps | ||
| 905 | (cl-push (cons (if ands 'psetq 'setq) | ||
| 906 | (apply 'append (nreverse loop-for-steps))) | ||
| 907 | loop-steps)))) | ||
| 908 | |||
| 909 | ((eq word 'repeat) | ||
| 910 | (let ((temp (gensym))) | ||
| 911 | (cl-push (list (list temp (cl-pop args))) loop-bindings) | ||
| 912 | (cl-push (list '>= (list 'setq temp (list '1- temp)) 0) loop-body))) | ||
| 913 | |||
| 914 | ((eq word 'collect) | ||
| 915 | (let ((what (cl-pop args)) | ||
| 916 | (var (cl-loop-handle-accum nil 'nreverse))) | ||
| 917 | (if (eq var loop-accum-var) | ||
| 918 | (cl-push (list 'progn (list 'push what var) t) loop-body) | ||
| 919 | (cl-push (list 'progn | ||
| 920 | (list 'setq var (list 'nconc var (list 'list what))) | ||
| 921 | t) loop-body)))) | ||
| 922 | |||
| 923 | ((memq word '(nconc nconcing append appending)) | ||
| 924 | (let ((what (cl-pop args)) | ||
| 925 | (var (cl-loop-handle-accum nil 'nreverse))) | ||
| 926 | (cl-push (list 'progn | ||
| 927 | (list 'setq var | ||
| 928 | (if (eq var loop-accum-var) | ||
| 929 | (list 'nconc | ||
| 930 | (list (if (memq word '(nconc nconcing)) | ||
| 931 | 'nreverse 'reverse) | ||
| 932 | what) | ||
| 933 | var) | ||
| 934 | (list (if (memq word '(nconc nconcing)) | ||
| 935 | 'nconc 'append) | ||
| 936 | var what))) t) loop-body))) | ||
| 937 | |||
| 938 | ((memq word '(concat concating)) | ||
| 939 | (let ((what (cl-pop args)) | ||
| 940 | (var (cl-loop-handle-accum ""))) | ||
| 941 | (cl-push (list 'progn (list 'callf 'concat var what) t) loop-body))) | ||
| 942 | |||
| 943 | ((memq word '(vconcat vconcating)) | ||
| 944 | (let ((what (cl-pop args)) | ||
| 945 | (var (cl-loop-handle-accum []))) | ||
| 946 | (cl-push (list 'progn (list 'callf 'vconcat var what) t) loop-body))) | ||
| 947 | |||
| 948 | ((memq word '(sum summing)) | ||
| 949 | (let ((what (cl-pop args)) | ||
| 950 | (var (cl-loop-handle-accum 0))) | ||
| 951 | (cl-push (list 'progn (list 'incf var what) t) loop-body))) | ||
| 952 | |||
| 953 | ((memq word '(count counting)) | ||
| 954 | (let ((what (cl-pop args)) | ||
| 955 | (var (cl-loop-handle-accum 0))) | ||
| 956 | (cl-push (list 'progn (list 'if what (list 'incf var)) t) loop-body))) | ||
| 957 | |||
| 958 | ((memq word '(minimize minimizing maximize maximizing)) | ||
| 959 | (let* ((what (cl-pop args)) | ||
| 960 | (temp (if (cl-simple-expr-p what) what (gensym))) | ||
| 961 | (var (cl-loop-handle-accum nil)) | ||
| 962 | (func (intern (substring (symbol-name word) 0 3))) | ||
| 963 | (set (list 'setq var (list 'if var (list func var temp) temp)))) | ||
| 964 | (cl-push (list 'progn (if (eq temp what) set | ||
| 965 | (list 'let (list (list temp what)) set)) | ||
| 966 | t) loop-body))) | ||
| 967 | |||
| 968 | ((eq word 'with) | ||
| 969 | (let ((bindings nil)) | ||
| 970 | (while (progn (cl-push (list (cl-pop args) | ||
| 971 | (and (eq (car args) '=) (cl-pop2 args))) | ||
| 972 | bindings) | ||
| 973 | (eq (car args) 'and)) | ||
| 974 | (cl-pop args)) | ||
| 975 | (cl-push (nreverse bindings) loop-bindings))) | ||
| 976 | |||
| 977 | ((eq word 'while) | ||
| 978 | (cl-push (cl-pop args) loop-body)) | ||
| 979 | |||
| 980 | ((eq word 'until) | ||
| 981 | (cl-push (list 'not (cl-pop args)) loop-body)) | ||
| 982 | |||
| 983 | ((eq word 'always) | ||
| 984 | (or loop-finish-flag (setq loop-finish-flag (gensym))) | ||
| 985 | (cl-push (list 'setq loop-finish-flag (cl-pop args)) loop-body) | ||
| 986 | (setq loop-result t)) | ||
| 987 | |||
| 988 | ((eq word 'never) | ||
| 989 | (or loop-finish-flag (setq loop-finish-flag (gensym))) | ||
| 990 | (cl-push (list 'setq loop-finish-flag (list 'not (cl-pop args))) | ||
| 991 | loop-body) | ||
| 992 | (setq loop-result t)) | ||
| 993 | |||
| 994 | ((eq word 'thereis) | ||
| 995 | (or loop-finish-flag (setq loop-finish-flag (gensym))) | ||
| 996 | (or loop-result-var (setq loop-result-var (gensym))) | ||
| 997 | (cl-push (list 'setq loop-finish-flag | ||
| 998 | (list 'not (list 'setq loop-result-var (cl-pop args)))) | ||
| 999 | loop-body)) | ||
| 1000 | |||
| 1001 | ((memq word '(if when unless)) | ||
| 1002 | (let* ((cond (cl-pop args)) | ||
| 1003 | (then (let ((loop-body nil)) | ||
| 1004 | (cl-parse-loop-clause) | ||
| 1005 | (cl-loop-build-ands (nreverse loop-body)))) | ||
| 1006 | (else (let ((loop-body nil)) | ||
| 1007 | (if (eq (car args) 'else) | ||
| 1008 | (progn (cl-pop args) (cl-parse-loop-clause))) | ||
| 1009 | (cl-loop-build-ands (nreverse loop-body)))) | ||
| 1010 | (simple (and (eq (car then) t) (eq (car else) t)))) | ||
| 1011 | (if (eq (car args) 'end) (cl-pop args)) | ||
| 1012 | (if (eq word 'unless) (setq then (prog1 else (setq else then)))) | ||
| 1013 | (let ((form (cons (if simple (cons 'progn (nth 1 then)) (nth 2 then)) | ||
| 1014 | (if simple (nth 1 else) (list (nth 2 else)))))) | ||
| 1015 | (if (cl-expr-contains form 'it) | ||
| 1016 | (let ((temp (gensym))) | ||
| 1017 | (cl-push (list temp) loop-bindings) | ||
| 1018 | (setq form (list* 'if (list 'setq temp cond) | ||
| 1019 | (subst temp 'it form)))) | ||
| 1020 | (setq form (list* 'if cond form))) | ||
| 1021 | (cl-push (if simple (list 'progn form t) form) loop-body)))) | ||
| 1022 | |||
| 1023 | ((memq word '(do doing)) | ||
| 1024 | (let ((body nil)) | ||
| 1025 | (or (consp (car args)) (error "Syntax error on `do' clause")) | ||
| 1026 | (while (consp (car args)) (cl-push (cl-pop args) body)) | ||
| 1027 | (cl-push (cons 'progn (nreverse (cons t body))) loop-body))) | ||
| 1028 | |||
| 1029 | ((eq word 'return) | ||
| 1030 | (or loop-finish-flag (setq loop-finish-flag (gensym))) | ||
| 1031 | (or loop-result-var (setq loop-result-var (gensym))) | ||
| 1032 | (cl-push (list 'setq loop-result-var (cl-pop args) | ||
| 1033 | loop-finish-flag nil) loop-body)) | ||
| 1034 | |||
| 1035 | (t | ||
| 1036 | (let ((handler (and (symbolp word) (get word 'cl-loop-handler)))) | ||
| 1037 | (or handler (error "Expected a loop keyword, found %s" word)) | ||
| 1038 | (funcall handler)))) | ||
| 1039 | (if (eq (car args) 'and) | ||
| 1040 | (progn (cl-pop args) (cl-parse-loop-clause))))) | ||
| 1041 | |||
| 1042 | (defun cl-loop-let (specs body par) ; uses loop-* | ||
| 1043 | (let ((p specs) (temps nil) (new nil)) | ||
| 1044 | (while (and p (or (symbolp (car-safe (car p))) (null (cadar p)))) | ||
| 1045 | (setq p (cdr p))) | ||
| 1046 | (and par p | ||
| 1047 | (progn | ||
| 1048 | (setq par nil p specs) | ||
| 1049 | (while p | ||
| 1050 | (or (cl-const-expr-p (cadar p)) | ||
| 1051 | (let ((temp (gensym))) | ||
| 1052 | (cl-push (list temp (cadar p)) temps) | ||
| 1053 | (setcar (cdar p) temp))) | ||
| 1054 | (setq p (cdr p))))) | ||
| 1055 | (while specs | ||
| 1056 | (if (and (consp (car specs)) (listp (caar specs))) | ||
| 1057 | (let* ((spec (caar specs)) (nspecs nil) | ||
| 1058 | (expr (cadr (cl-pop specs))) | ||
| 1059 | (temp (cdr (or (assq spec loop-destr-temps) | ||
| 1060 | (car (cl-push (cons spec (or (last spec 0) | ||
| 1061 | (gensym))) | ||
| 1062 | loop-destr-temps)))))) | ||
| 1063 | (cl-push (list temp expr) new) | ||
| 1064 | (while (consp spec) | ||
| 1065 | (cl-push (list (cl-pop spec) | ||
| 1066 | (and expr (list (if spec 'pop 'car) temp))) | ||
| 1067 | nspecs)) | ||
| 1068 | (setq specs (nconc (nreverse nspecs) specs))) | ||
| 1069 | (cl-push (cl-pop specs) new))) | ||
| 1070 | (if (eq body 'setq) | ||
| 1071 | (let ((set (cons (if par 'psetq 'setq) (apply 'nconc (nreverse new))))) | ||
| 1072 | (if temps (list 'let* (nreverse temps) set) set)) | ||
| 1073 | (list* (if par 'let 'let*) | ||
| 1074 | (nconc (nreverse temps) (nreverse new)) body)))) | ||
| 1075 | |||
| 1076 | (defun cl-loop-handle-accum (def &optional func) ; uses args, loop-* | ||
| 1077 | (if (eq (car args) 'into) | ||
| 1078 | (let ((var (cl-pop2 args))) | ||
| 1079 | (or (memq var loop-accum-vars) | ||
| 1080 | (progn (cl-push (list (list var def)) loop-bindings) | ||
| 1081 | (cl-push var loop-accum-vars))) | ||
| 1082 | var) | ||
| 1083 | (or loop-accum-var | ||
| 1084 | (progn | ||
| 1085 | (cl-push (list (list (setq loop-accum-var (gensym)) def)) | ||
| 1086 | loop-bindings) | ||
| 1087 | (setq loop-result (if func (list func loop-accum-var) | ||
| 1088 | loop-accum-var)) | ||
| 1089 | loop-accum-var)))) | ||
| 1090 | |||
| 1091 | (defun cl-loop-build-ands (clauses) | ||
| 1092 | (let ((ands nil) | ||
| 1093 | (body nil)) | ||
| 1094 | (while clauses | ||
| 1095 | (if (and (eq (car-safe (car clauses)) 'progn) | ||
| 1096 | (eq (car (last (car clauses))) t)) | ||
| 1097 | (if (cdr clauses) | ||
| 1098 | (setq clauses (cons (nconc (butlast (car clauses)) | ||
| 1099 | (if (eq (car-safe (cadr clauses)) | ||
| 1100 | 'progn) | ||
| 1101 | (cdadr clauses) | ||
| 1102 | (list (cadr clauses)))) | ||
| 1103 | (cddr clauses))) | ||
| 1104 | (setq body (cdr (butlast (cl-pop clauses))))) | ||
| 1105 | (cl-push (cl-pop clauses) ands))) | ||
| 1106 | (setq ands (or (nreverse ands) (list t))) | ||
| 1107 | (list (if (cdr ands) (cons 'and ands) (car ands)) | ||
| 1108 | body | ||
| 1109 | (let ((full (if body | ||
| 1110 | (append ands (list (cons 'progn (append body '(t))))) | ||
| 1111 | ands))) | ||
| 1112 | (if (cdr full) (cons 'and full) (car full)))))) | ||
| 1113 | |||
| 1114 | |||
| 1115 | ;;; Other iteration control structures. | ||
| 1116 | |||
| 1117 | (defmacro do (steps endtest &rest body) | ||
| 1118 | "The Common Lisp `do' loop. | ||
| 1119 | Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" | ||
| 1120 | (cl-expand-do-loop steps endtest body nil)) | ||
| 1121 | |||
| 1122 | (defmacro do* (steps endtest &rest body) | ||
| 1123 | "The Common Lisp `do*' loop. | ||
| 1124 | Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)" | ||
| 1125 | (cl-expand-do-loop steps endtest body t)) | ||
| 1126 | |||
| 1127 | (defun cl-expand-do-loop (steps endtest body star) | ||
| 1128 | (list 'block nil | ||
| 1129 | (list* (if star 'let* 'let) | ||
| 1130 | (mapcar (function (lambda (c) | ||
| 1131 | (if (consp c) (list (car c) (nth 1 c)) c))) | ||
| 1132 | steps) | ||
| 1133 | (list* 'while (list 'not (car endtest)) | ||
| 1134 | (append body | ||
| 1135 | (let ((sets (mapcar | ||
| 1136 | (function | ||
| 1137 | (lambda (c) | ||
| 1138 | (and (consp c) (cdr (cdr c)) | ||
| 1139 | (list (car c) (nth 2 c))))) | ||
| 1140 | steps))) | ||
| 1141 | (setq sets (delq nil sets)) | ||
| 1142 | (and sets | ||
| 1143 | (list (cons (if (or star (not (cdr sets))) | ||
| 1144 | 'setq 'psetq) | ||
| 1145 | (apply 'append sets))))))) | ||
| 1146 | (or (cdr endtest) '(nil))))) | ||
| 1147 | |||
| 1148 | (defmacro dolist (spec &rest body) | ||
| 1149 | "(dolist (VAR LIST [RESULT]) BODY...): loop over a list. | ||
| 1150 | Evaluate BODY with VAR bound to each `car' from LIST, in turn. | ||
| 1151 | Then evaluate RESULT to get return value, default nil." | ||
| 1152 | (let ((temp (gensym "--dolist-temp--"))) | ||
| 1153 | (list 'block nil | ||
| 1154 | (list* 'let (list (list temp (nth 1 spec)) (car spec)) | ||
| 1155 | (list* 'while temp (list 'setq (car spec) (list 'car temp)) | ||
| 1156 | (append body (list (list 'setq temp | ||
| 1157 | (list 'cdr temp))))) | ||
| 1158 | (if (cdr (cdr spec)) | ||
| 1159 | (cons (list 'setq (car spec) nil) (cdr (cdr spec))) | ||
| 1160 | '(nil)))))) | ||
| 1161 | |||
| 1162 | (defmacro dotimes (spec &rest body) | ||
| 1163 | "(dotimes (VAR COUNT [RESULT]) BODY...): loop a certain number of times. | ||
| 1164 | Evaluate BODY with VAR bound to successive integers from 0, inclusive, | ||
| 1165 | to COUNT, exclusive. Then evaluate RESULT to get return value, default | ||
| 1166 | nil." | ||
| 1167 | (let ((temp (gensym "--dotimes-temp--"))) | ||
| 1168 | (list 'block nil | ||
| 1169 | (list* 'let (list (list temp (nth 1 spec)) (list (car spec) 0)) | ||
| 1170 | (list* 'while (list '< (car spec) temp) | ||
| 1171 | (append body (list (list 'incf (car spec))))) | ||
| 1172 | (or (cdr (cdr spec)) '(nil)))))) | ||
| 1173 | |||
| 1174 | (defmacro do-symbols (spec &rest body) | ||
| 1175 | "(dosymbols (VAR [OBARRAY [RESULT]]) BODY...): loop over all symbols. | ||
| 1176 | Evaluate BODY with VAR bound to each interned symbol, or to each symbol | ||
| 1177 | from OBARRAY." | ||
| 1178 | ;; Apparently this doesn't have an implicit block. | ||
| 1179 | (list 'block nil | ||
| 1180 | (list 'let (list (car spec)) | ||
| 1181 | (list* 'mapatoms | ||
| 1182 | (list 'function (list* 'lambda (list (car spec)) body)) | ||
| 1183 | (and (cadr spec) (list (cadr spec)))) | ||
| 1184 | (caddr spec)))) | ||
| 1185 | |||
| 1186 | (defmacro do-all-symbols (spec &rest body) | ||
| 1187 | (list* 'do-symbols (list (car spec) nil (cadr spec)) body)) | ||
| 1188 | |||
| 1189 | |||
| 1190 | ;;; Assignments. | ||
| 1191 | |||
| 1192 | (defmacro psetq (&rest args) | ||
| 1193 | "(psetq SYM VAL SYM VAL ...): set SYMs to the values VALs in parallel. | ||
| 1194 | This is like `setq', except that all VAL forms are evaluated (in order) | ||
| 1195 | before assigning any symbols SYM to the corresponding values." | ||
| 1196 | (cons 'psetf args)) | ||
| 1197 | |||
| 1198 | |||
| 1199 | ;;; Binding control structures. | ||
| 1200 | |||
| 1201 | (defmacro progv (symbols values &rest body) | ||
| 1202 | "(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. | ||
| 1203 | The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. | ||
| 1204 | Each SYMBOL in the first list is bound to the corresponding VALUE in the | ||
| 1205 | second list (or made unbound if VALUES is shorter than SYMBOLS); then the | ||
| 1206 | BODY forms are executed and their result is returned. This is much like | ||
| 1207 | a `let' form, except that the list of symbols can be computed at run-time." | ||
| 1208 | (list 'let '((cl-progv-save nil)) | ||
| 1209 | (list 'unwind-protect | ||
| 1210 | (list* 'progn (list 'cl-progv-before symbols values) body) | ||
| 1211 | '(cl-progv-after)))) | ||
| 1212 | |||
| 1213 | ;;; This should really have some way to shadow 'byte-compile properties, etc. | ||
| 1214 | (defmacro flet (bindings &rest body) | ||
| 1215 | "(flet ((FUNC ARGLIST BODY...) ...) FORM...): make temporary function defns. | ||
| 1216 | This is an analogue of `let' that operates on the function cell of FUNC | ||
| 1217 | rather than its value cell. The FORMs are evaluated with the specified | ||
| 1218 | function definitions in place, then the definitions are undone (the FUNCs | ||
| 1219 | go back to their previous definitions, or lack thereof)." | ||
| 1220 | (list* 'letf* | ||
| 1221 | (mapcar | ||
| 1222 | (function | ||
| 1223 | (lambda (x) | ||
| 1224 | (let ((func (list 'function* | ||
| 1225 | (list 'lambda (cadr x) | ||
| 1226 | (list* 'block (car x) (cddr x)))))) | ||
| 1227 | (if (and (cl-compiling-file) | ||
| 1228 | (boundp 'byte-compile-function-environment)) | ||
| 1229 | (cl-push (cons (car x) (eval func)) | ||
| 1230 | byte-compile-function-environment)) | ||
| 1231 | (list (list 'symbol-function (list 'quote (car x))) func)))) | ||
| 1232 | bindings) | ||
| 1233 | body)) | ||
| 1234 | |||
| 1235 | (defmacro labels (&rest args) (cons 'flet args)) | ||
| 1236 | |||
| 1237 | ;; The following ought to have a better definition for use with newer | ||
| 1238 | ;; byte compilers. | ||
| 1239 | (defmacro macrolet (bindings &rest body) | ||
| 1240 | "(macrolet ((NAME ARGLIST BODY...) ...) FORM...): make temporary macro defns. | ||
| 1241 | This is like `flet', but for macros instead of functions." | ||
| 1242 | (if (cdr bindings) | ||
| 1243 | (list 'macrolet | ||
| 1244 | (list (car bindings)) (list* 'macrolet (cdr bindings) body)) | ||
| 1245 | (if (null bindings) (cons 'progn body) | ||
| 1246 | (let* ((name (caar bindings)) | ||
| 1247 | (res (cl-transform-lambda (cdar bindings) name))) | ||
| 1248 | (eval (car res)) | ||
| 1249 | (cl-macroexpand-all (cons 'progn body) | ||
| 1250 | (cons (list* name 'lambda (cdr res)) | ||
| 1251 | cl-macro-environment)))))) | ||
| 1252 | |||
| 1253 | (defmacro symbol-macrolet (bindings &rest body) | ||
| 1254 | "(symbol-macrolet ((NAME EXPANSION) ...) FORM...): make symbol macro defns. | ||
| 1255 | Within the body FORMs, references to the variable NAME will be replaced | ||
| 1256 | by EXPANSION, and (setq NAME ...) will act like (setf EXPANSION ...)." | ||
| 1257 | (if (cdr bindings) | ||
| 1258 | (list 'symbol-macrolet | ||
| 1259 | (list (car bindings)) (list* 'symbol-macrolet (cdr bindings) body)) | ||
| 1260 | (if (null bindings) (cons 'progn body) | ||
| 1261 | (cl-macroexpand-all (cons 'progn body) | ||
| 1262 | (cons (list (symbol-name (caar bindings)) | ||
| 1263 | (cadar bindings)) | ||
| 1264 | cl-macro-environment))))) | ||
| 1265 | |||
| 1266 | (defvar cl-closure-vars nil) | ||
| 1267 | (defmacro lexical-let (bindings &rest body) | ||
| 1268 | "(lexical-let BINDINGS BODY...): like `let', but lexically scoped. | ||
| 1269 | The main visible difference is that lambdas inside BODY will create | ||
| 1270 | lexical closures as in Common Lisp." | ||
| 1271 | (let* ((cl-closure-vars cl-closure-vars) | ||
| 1272 | (vars (mapcar (function | ||
| 1273 | (lambda (x) | ||
| 1274 | (or (consp x) (setq x (list x))) | ||
| 1275 | (cl-push (gensym (format "--%s--" (car x))) | ||
| 1276 | cl-closure-vars) | ||
| 1277 | (list (car x) (cadr x) (car cl-closure-vars)))) | ||
| 1278 | bindings)) | ||
| 1279 | (ebody | ||
| 1280 | (cl-macroexpand-all | ||
| 1281 | (cons 'progn body) | ||
| 1282 | (nconc (mapcar (function (lambda (x) | ||
| 1283 | (list (symbol-name (car x)) | ||
| 1284 | (list 'symbol-value (caddr x)) | ||
| 1285 | t))) vars) | ||
| 1286 | (list '(defun . cl-defun-expander)) | ||
| 1287 | cl-macro-environment)))) | ||
| 1288 | (if (not (get (car (last cl-closure-vars)) 'used)) | ||
| 1289 | (list 'let (mapcar (function (lambda (x) | ||
| 1290 | (list (caddr x) (cadr x)))) vars) | ||
| 1291 | (sublis (mapcar (function (lambda (x) | ||
| 1292 | (cons (caddr x) | ||
| 1293 | (list 'quote (caddr x))))) | ||
| 1294 | vars) | ||
| 1295 | ebody)) | ||
| 1296 | (list 'let (mapcar (function (lambda (x) | ||
| 1297 | (list (caddr x) | ||
| 1298 | (list 'make-symbol | ||
| 1299 | (format "--%s--" (car x)))))) | ||
| 1300 | vars) | ||
| 1301 | (apply 'append '(setf) | ||
| 1302 | (mapcar (function | ||
| 1303 | (lambda (x) | ||
| 1304 | (list (list 'symbol-value (caddr x)) (cadr x)))) | ||
| 1305 | vars)) | ||
| 1306 | ebody)))) | ||
| 1307 | |||
| 1308 | (defmacro lexical-let* (bindings &rest body) | ||
| 1309 | "(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. | ||
| 1310 | The main visible difference is that lambdas inside BODY will create | ||
| 1311 | lexical closures as in Common Lisp." | ||
| 1312 | (if (null bindings) (cons 'progn body) | ||
| 1313 | (setq bindings (reverse bindings)) | ||
| 1314 | (while bindings | ||
| 1315 | (setq body (list (list* 'lexical-let (list (cl-pop bindings)) body)))) | ||
| 1316 | (car body))) | ||
| 1317 | |||
| 1318 | (defun cl-defun-expander (func &rest rest) | ||
| 1319 | (list 'progn | ||
| 1320 | (list 'defalias (list 'quote func) | ||
| 1321 | (list 'function (cons 'lambda rest))) | ||
| 1322 | (list 'quote func))) | ||
| 1323 | |||
| 1324 | |||
| 1325 | ;;; Multiple values. | ||
| 1326 | |||
| 1327 | (defmacro multiple-value-bind (vars form &rest body) | ||
| 1328 | "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. | ||
| 1329 | FORM must return a list; the BODY is then executed with the first N elements | ||
| 1330 | of this list bound (`let'-style) to each of the symbols SYM in turn. This | ||
| 1331 | is analogous to the Common Lisp `multiple-value-bind' macro, using lists to | ||
| 1332 | simulate true multiple return values. For compatibility, (values A B C) is | ||
| 1333 | a synonym for (list A B C)." | ||
| 1334 | (let ((temp (gensym)) (n -1)) | ||
| 1335 | (list* 'let* (cons (list temp form) | ||
| 1336 | (mapcar (function | ||
| 1337 | (lambda (v) | ||
| 1338 | (list v (list 'nth (setq n (1+ n)) temp)))) | ||
| 1339 | vars)) | ||
| 1340 | body))) | ||
| 1341 | |||
| 1342 | (defmacro multiple-value-setq (vars form) | ||
| 1343 | "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. | ||
| 1344 | FORM must return a list; the first N elements of this list are stored in | ||
| 1345 | each of the symbols SYM in turn. This is analogous to the Common Lisp | ||
| 1346 | `multiple-value-setq' macro, using lists to simulate true multiple return | ||
| 1347 | values. For compatibility, (values A B C) is a synonym for (list A B C)." | ||
| 1348 | (cond ((null vars) (list 'progn form nil)) | ||
| 1349 | ((null (cdr vars)) (list 'setq (car vars) (list 'car form))) | ||
| 1350 | (t | ||
| 1351 | (let* ((temp (gensym)) (n 0)) | ||
| 1352 | (list 'let (list (list temp form)) | ||
| 1353 | (list 'prog1 (list 'setq (cl-pop vars) (list 'car temp)) | ||
| 1354 | (cons 'setq (apply 'nconc | ||
| 1355 | (mapcar (function | ||
| 1356 | (lambda (v) | ||
| 1357 | (list v (list | ||
| 1358 | 'nth | ||
| 1359 | (setq n (1+ n)) | ||
| 1360 | temp)))) | ||
| 1361 | vars))))))))) | ||
| 1362 | |||
| 1363 | |||
| 1364 | ;;; Declarations. | ||
| 1365 | |||
| 1366 | (defmacro locally (&rest body) (cons 'progn body)) | ||
| 1367 | (defmacro the (type form) form) | ||
| 1368 | |||
| 1369 | (defvar cl-proclaim-history t) ; for future compilers | ||
| 1370 | (defvar cl-declare-stack t) ; for future compilers | ||
| 1371 | |||
| 1372 | (defun cl-do-proclaim (spec hist) | ||
| 1373 | (and hist (listp cl-proclaim-history) (cl-push spec cl-proclaim-history)) | ||
| 1374 | (cond ((eq (car-safe spec) 'special) | ||
| 1375 | (if (boundp 'byte-compile-bound-variables) | ||
| 1376 | (setq byte-compile-bound-variables | ||
| 1377 | (append (cdr spec) byte-compile-bound-variables)))) | ||
| 1378 | |||
| 1379 | ((eq (car-safe spec) 'inline) | ||
| 1380 | (while (setq spec (cdr spec)) | ||
| 1381 | (or (memq (get (car spec) 'byte-optimizer) | ||
| 1382 | '(nil byte-compile-inline-expand)) | ||
| 1383 | (error "%s already has a byte-optimizer, can't make it inline" | ||
| 1384 | (car spec))) | ||
| 1385 | (put (car spec) 'byte-optimizer 'byte-compile-inline-expand))) | ||
| 1386 | |||
| 1387 | ((eq (car-safe spec) 'notinline) | ||
| 1388 | (while (setq spec (cdr spec)) | ||
| 1389 | (if (eq (get (car spec) 'byte-optimizer) | ||
| 1390 | 'byte-compile-inline-expand) | ||
| 1391 | (put (car spec) 'byte-optimizer nil)))) | ||
| 1392 | |||
| 1393 | ((eq (car-safe spec) 'optimize) | ||
| 1394 | (let ((speed (assq (nth 1 (assq 'speed (cdr spec))) | ||
| 1395 | '((0 nil) (1 t) (2 t) (3 t)))) | ||
| 1396 | (safety (assq (nth 1 (assq 'safety (cdr spec))) | ||
| 1397 | '((0 t) (1 t) (2 t) (3 nil))))) | ||
| 1398 | (if speed (setq cl-optimize-speed (car speed) | ||
| 1399 | byte-optimize (nth 1 speed))) | ||
| 1400 | (if safety (setq cl-optimize-safety (car safety) | ||
| 1401 | byte-compile-delete-errors (nth 1 safety))))) | ||
| 1402 | |||
| 1403 | ((and (eq (car-safe spec) 'warn) (boundp 'byte-compile-warnings)) | ||
| 1404 | (if (eq byte-compile-warnings t) | ||
| 1405 | (setq byte-compile-warnings byte-compile-warning-types)) | ||
| 1406 | (while (setq spec (cdr spec)) | ||
| 1407 | (if (consp (car spec)) | ||
| 1408 | (if (eq (cadar spec) 0) | ||
| 1409 | (setq byte-compile-warnings | ||
| 1410 | (delq (caar spec) byte-compile-warnings)) | ||
| 1411 | (setq byte-compile-warnings | ||
| 1412 | (adjoin (caar spec) byte-compile-warnings))))))) | ||
| 1413 | nil) | ||
| 1414 | |||
| 1415 | ;;; Process any proclamations made before cl-macs was loaded. | ||
| 1416 | (defvar cl-proclaims-deferred) | ||
| 1417 | (let ((p (reverse cl-proclaims-deferred))) | ||
| 1418 | (while p (cl-do-proclaim (cl-pop p) t)) | ||
| 1419 | (setq cl-proclaims-deferred nil)) | ||
| 1420 | |||
| 1421 | (defmacro declare (&rest specs) | ||
| 1422 | (if (cl-compiling-file) | ||
| 1423 | (while specs | ||
| 1424 | (if (listp cl-declare-stack) (cl-push (car specs) cl-declare-stack)) | ||
| 1425 | (cl-do-proclaim (cl-pop specs) nil))) | ||
| 1426 | nil) | ||
| 1427 | |||
| 1428 | |||
| 1429 | |||
| 1430 | ;;; Generalized variables. | ||
| 1431 | |||
| 1432 | (defmacro define-setf-method (func args &rest body) | ||
| 1433 | "(define-setf-method NAME ARGLIST BODY...): define a `setf' method. | ||
| 1434 | This method shows how to handle `setf's to places of the form (NAME ARGS...). | ||
| 1435 | The argument forms ARGS are bound according to ARGLIST, as if NAME were | ||
| 1436 | going to be expanded as a macro, then the BODY forms are executed and must | ||
| 1437 | return a list of five elements: a temporary-variables list, a value-forms | ||
| 1438 | list, a store-variables list (of length one), a store-form, and an access- | ||
| 1439 | form. See `defsetf' for a simpler way to define most setf-methods." | ||
| 1440 | (append '(eval-when (compile load eval)) | ||
| 1441 | (if (stringp (car body)) | ||
| 1442 | (list (list 'put (list 'quote func) '(quote setf-documentation) | ||
| 1443 | (cl-pop body)))) | ||
| 1444 | (list (cl-transform-function-property | ||
| 1445 | func 'setf-method (cons args body))))) | ||
| 1446 | |||
| 1447 | (defmacro defsetf (func arg1 &rest args) | ||
| 1448 | "(defsetf NAME FUNC): define a `setf' method. | ||
| 1449 | This macro is an easy-to-use substitute for `define-setf-method' that works | ||
| 1450 | well for simple place forms. In the simple `defsetf' form, `setf's of | ||
| 1451 | the form (setf (NAME ARGS...) VAL) are transformed to function or macro | ||
| 1452 | calls of the form (FUNC ARGS... VAL). Example: (defsetf aref aset). | ||
| 1453 | Alternate form: (defsetf NAME ARGLIST (STORE) BODY...). | ||
| 1454 | Here, the above `setf' call is expanded by binding the argument forms ARGS | ||
| 1455 | according to ARGLIST, binding the value form VAL to STORE, then executing | ||
| 1456 | BODY, which must return a Lisp form that does the necessary `setf' operation. | ||
| 1457 | Actually, ARGLIST and STORE may be bound to temporary variables which are | ||
| 1458 | introduced automatically to preserve proper execution order of the arguments. | ||
| 1459 | Example: (defsetf nth (n x) (v) (list 'setcar (list 'nthcdr n x) v))." | ||
| 1460 | (if (listp arg1) | ||
| 1461 | (let* ((largs nil) (largsr nil) | ||
| 1462 | (temps nil) (tempsr nil) | ||
| 1463 | (restarg nil) (rest-temps nil) | ||
| 1464 | (store-var (car (prog1 (car args) (setq args (cdr args))))) | ||
| 1465 | (store-temp (intern (format "--%s--temp--" store-var))) | ||
| 1466 | (lets1 nil) (lets2 nil) | ||
| 1467 | (docstr nil) (p arg1)) | ||
| 1468 | (if (stringp (car args)) | ||
| 1469 | (setq docstr (prog1 (car args) (setq args (cdr args))))) | ||
| 1470 | (while (and p (not (eq (car p) '&aux))) | ||
| 1471 | (if (eq (car p) '&rest) | ||
| 1472 | (setq p (cdr p) restarg (car p)) | ||
| 1473 | (or (memq (car p) '(&optional &key &allow-other-keys)) | ||
| 1474 | (setq largs (cons (if (consp (car p)) (car (car p)) (car p)) | ||
| 1475 | largs) | ||
| 1476 | temps (cons (intern (format "--%s--temp--" (car largs))) | ||
| 1477 | temps)))) | ||
| 1478 | (setq p (cdr p))) | ||
| 1479 | (setq largs (nreverse largs) temps (nreverse temps)) | ||
| 1480 | (if restarg | ||
| 1481 | (setq largsr (append largs (list restarg)) | ||
| 1482 | rest-temps (intern (format "--%s--temp--" restarg)) | ||
| 1483 | tempsr (append temps (list rest-temps))) | ||
| 1484 | (setq largsr largs tempsr temps)) | ||
| 1485 | (let ((p1 largs) (p2 temps)) | ||
| 1486 | (while p1 | ||
| 1487 | (setq lets1 (cons (list (car p2) | ||
| 1488 | (list 'gensym (format "--%s--" (car p1)))) | ||
| 1489 | lets1) | ||
| 1490 | lets2 (cons (list (car p1) (car p2)) lets2) | ||
| 1491 | p1 (cdr p1) p2 (cdr p2)))) | ||
| 1492 | (if restarg (setq lets2 (cons (list restarg rest-temps) lets2))) | ||
| 1493 | (append (list 'define-setf-method func arg1) | ||
| 1494 | (and docstr (list docstr)) | ||
| 1495 | (list | ||
| 1496 | (list 'let* | ||
| 1497 | (nreverse | ||
| 1498 | (cons (list store-temp | ||
| 1499 | (list 'gensym (format "--%s--" store-var))) | ||
| 1500 | (if restarg | ||
| 1501 | (append | ||
| 1502 | (list | ||
| 1503 | (list rest-temps | ||
| 1504 | (list 'mapcar '(quote gensym) | ||
| 1505 | restarg))) | ||
| 1506 | lets1) | ||
| 1507 | lets1))) | ||
| 1508 | (list 'list ; 'values | ||
| 1509 | (cons (if restarg 'list* 'list) tempsr) | ||
| 1510 | (cons (if restarg 'list* 'list) largsr) | ||
| 1511 | (list 'list store-temp) | ||
| 1512 | (cons 'let* | ||
| 1513 | (cons (nreverse | ||
| 1514 | (cons (list store-var store-temp) | ||
| 1515 | lets2)) | ||
| 1516 | args)) | ||
| 1517 | (cons (if restarg 'list* 'list) | ||
| 1518 | (cons (list 'quote func) tempsr))))))) | ||
| 1519 | (list 'defsetf func '(&rest args) '(store) | ||
| 1520 | (let ((call (list 'cons (list 'quote arg1) | ||
| 1521 | '(append args (list store))))) | ||
| 1522 | (if (car args) | ||
| 1523 | (list 'list '(quote progn) call 'store) | ||
| 1524 | call))))) | ||
| 1525 | |||
| 1526 | ;;; Some standard place types from Common Lisp. | ||
| 1527 | (defsetf aref aset) | ||
| 1528 | (defsetf car setcar) | ||
| 1529 | (defsetf cdr setcdr) | ||
| 1530 | (defsetf elt (seq n) (store) | ||
| 1531 | (list 'if (list 'listp seq) (list 'setcar (list 'nthcdr n seq) store) | ||
| 1532 | (list 'aset seq n store))) | ||
| 1533 | (defsetf get put) | ||
| 1534 | (defsetf get* (x y &optional d) (store) (list 'put x y store)) | ||
| 1535 | (defsetf gethash (x h &optional d) (store) (list 'cl-puthash x store h)) | ||
| 1536 | (defsetf nth (n x) (store) (list 'setcar (list 'nthcdr n x) store)) | ||
| 1537 | (defsetf subseq (seq start &optional end) (new) | ||
| 1538 | (list 'progn (list 'replace seq new ':start1 start ':end1 end) new)) | ||
| 1539 | (defsetf symbol-function fset) | ||
| 1540 | (defsetf symbol-plist setplist) | ||
| 1541 | (defsetf symbol-value set) | ||
| 1542 | |||
| 1543 | ;;; Various car/cdr aliases. Note that `cadr' is handled specially. | ||
| 1544 | (defsetf first setcar) | ||
| 1545 | (defsetf second (x) (store) (list 'setcar (list 'cdr x) store)) | ||
| 1546 | (defsetf third (x) (store) (list 'setcar (list 'cddr x) store)) | ||
| 1547 | (defsetf fourth (x) (store) (list 'setcar (list 'cdddr x) store)) | ||
| 1548 | (defsetf fifth (x) (store) (list 'setcar (list 'nthcdr 4 x) store)) | ||
| 1549 | (defsetf sixth (x) (store) (list 'setcar (list 'nthcdr 5 x) store)) | ||
| 1550 | (defsetf seventh (x) (store) (list 'setcar (list 'nthcdr 6 x) store)) | ||
| 1551 | (defsetf eighth (x) (store) (list 'setcar (list 'nthcdr 7 x) store)) | ||
| 1552 | (defsetf ninth (x) (store) (list 'setcar (list 'nthcdr 8 x) store)) | ||
| 1553 | (defsetf tenth (x) (store) (list 'setcar (list 'nthcdr 9 x) store)) | ||
| 1554 | (defsetf rest setcdr) | ||
| 1555 | |||
| 1556 | ;;; Some more Emacs-related place types. | ||
| 1557 | (defsetf buffer-file-name set-visited-file-name t) | ||
| 1558 | (defsetf buffer-modified-p set-buffer-modified-p t) | ||
| 1559 | (defsetf buffer-name rename-buffer t) | ||
| 1560 | (defsetf buffer-string () (store) | ||
| 1561 | (list 'progn '(erase-buffer) (list 'insert store))) | ||
| 1562 | (defsetf buffer-substring cl-set-buffer-substring) | ||
| 1563 | (defsetf current-buffer set-buffer) | ||
| 1564 | (defsetf current-case-table set-case-table) | ||
| 1565 | (defsetf current-column move-to-column t) | ||
| 1566 | (defsetf current-global-map use-global-map t) | ||
| 1567 | (defsetf current-input-mode () (store) | ||
| 1568 | (list 'progn (list 'apply 'set-input-mode store) store)) | ||
| 1569 | (defsetf current-local-map use-local-map t) | ||
| 1570 | (defsetf current-window-configuration set-window-configuration t) | ||
| 1571 | (defsetf default-file-modes set-default-file-modes t) | ||
| 1572 | (defsetf default-value set-default) | ||
| 1573 | (defsetf documentation-property put) | ||
| 1574 | (defsetf extent-data set-extent-data) | ||
| 1575 | (defsetf extent-face set-extent-face) | ||
| 1576 | (defsetf extent-priority set-extent-priority) | ||
| 1577 | (defsetf extent-end-position (ext) (store) | ||
| 1578 | (list 'progn (list 'set-extent-endpoints (list 'extent-start-position ext) | ||
| 1579 | store) store)) | ||
| 1580 | (defsetf extent-start-position (ext) (store) | ||
| 1581 | (list 'progn (list 'set-extent-endpoints store | ||
| 1582 | (list 'extent-end-position ext)) store)) | ||
| 1583 | (defsetf face-background (f &optional s) (x) (list 'set-face-background f x s)) | ||
| 1584 | (defsetf face-background-pixmap (f &optional s) (x) | ||
| 1585 | (list 'set-face-background-pixmap f x s)) | ||
| 1586 | (defsetf face-font (f &optional s) (x) (list 'set-face-font f x s)) | ||
| 1587 | (defsetf face-foreground (f &optional s) (x) (list 'set-face-foreground f x s)) | ||
| 1588 | (defsetf face-underline-p (f &optional s) (x) | ||
| 1589 | (list 'set-face-underline-p f x s)) | ||
| 1590 | (defsetf file-modes set-file-modes t) | ||
| 1591 | (defsetf frame-height set-screen-height t) | ||
| 1592 | (defsetf frame-parameters modify-frame-parameters t) | ||
| 1593 | (defsetf frame-visible-p cl-set-frame-visible-p) | ||
| 1594 | (defsetf frame-width set-screen-width t) | ||
| 1595 | (defsetf getenv setenv t) | ||
| 1596 | (defsetf get-register set-register) | ||
| 1597 | (defsetf global-key-binding global-set-key) | ||
| 1598 | (defsetf keymap-parent set-keymap-parent) | ||
| 1599 | (defsetf local-key-binding local-set-key) | ||
| 1600 | (defsetf mark set-mark t) | ||
| 1601 | (defsetf mark-marker set-mark t) | ||
| 1602 | (defsetf marker-position set-marker t) | ||
| 1603 | (defsetf match-data store-match-data t) | ||
| 1604 | (defsetf mouse-position (scr) (store) | ||
| 1605 | (list 'set-mouse-position scr (list 'car store) (list 'cadr store) | ||
| 1606 | (list 'cddr store))) | ||
| 1607 | (defsetf overlay-get overlay-put) | ||
| 1608 | (defsetf overlay-start (ov) (store) | ||
| 1609 | (list 'progn (list 'move-overlay ov store (list 'overlay-end ov)) store)) | ||
| 1610 | (defsetf overlay-end (ov) (store) | ||
| 1611 | (list 'progn (list 'move-overlay ov (list 'overlay-start ov) store) store)) | ||
| 1612 | (defsetf point goto-char) | ||
| 1613 | (defsetf point-marker goto-char t) | ||
| 1614 | (defsetf point-max () (store) | ||
| 1615 | (list 'progn (list 'narrow-to-region '(point-min) store) store)) | ||
| 1616 | (defsetf point-min () (store) | ||
| 1617 | (list 'progn (list 'narrow-to-region store '(point-max)) store)) | ||
| 1618 | (defsetf process-buffer set-process-buffer) | ||
| 1619 | (defsetf process-filter set-process-filter) | ||
| 1620 | (defsetf process-sentinel set-process-sentinel) | ||
| 1621 | (defsetf read-mouse-position (scr) (store) | ||
| 1622 | (list 'set-mouse-position scr (list 'car store) (list 'cdr store))) | ||
| 1623 | (defsetf screen-height set-screen-height t) | ||
| 1624 | (defsetf screen-width set-screen-width t) | ||
| 1625 | (defsetf selected-window select-window) | ||
| 1626 | (defsetf selected-screen select-screen) | ||
| 1627 | (defsetf selected-frame select-frame) | ||
| 1628 | (defsetf standard-case-table set-standard-case-table) | ||
| 1629 | (defsetf syntax-table set-syntax-table) | ||
| 1630 | (defsetf visited-file-modtime set-visited-file-modtime t) | ||
| 1631 | (defsetf window-buffer set-window-buffer t) | ||
| 1632 | (defsetf window-display-table set-window-display-table t) | ||
| 1633 | (defsetf window-dedicated-p set-window-dedicated-p t) | ||
| 1634 | (defsetf window-height () (store) | ||
| 1635 | (list 'progn (list 'enlarge-window (list '- store '(window-height))) store)) | ||
| 1636 | (defsetf window-hscroll set-window-hscroll) | ||
| 1637 | (defsetf window-point set-window-point) | ||
| 1638 | (defsetf window-start set-window-start) | ||
| 1639 | (defsetf window-width () (store) | ||
| 1640 | (list 'progn (list 'enlarge-window (list '- store '(window-width)) t) store)) | ||
| 1641 | (defsetf x-get-cutbuffer x-store-cutbuffer t) | ||
| 1642 | (defsetf x-get-cut-buffer x-store-cut-buffer t) ; groan. | ||
| 1643 | (defsetf x-get-secondary-selection x-own-secondary-selection t) | ||
| 1644 | (defsetf x-get-selection x-own-selection t) | ||
| 1645 | |||
| 1646 | ;;; More complex setf-methods. | ||
| 1647 | ;;; These should take &environment arguments, but since full arglists aren't | ||
| 1648 | ;;; available while compiling cl-macs, we fake it by referring to the global | ||
| 1649 | ;;; variable cl-macro-environment directly. | ||
| 1650 | |||
| 1651 | (define-setf-method apply (func arg1 &rest rest) | ||
| 1652 | (or (and (memq (car-safe func) '(quote function function*)) | ||
| 1653 | (symbolp (car-safe (cdr-safe func)))) | ||
| 1654 | (error "First arg to apply in setf is not (function SYM): %s" func)) | ||
| 1655 | (let* ((form (cons (nth 1 func) (cons arg1 rest))) | ||
| 1656 | (method (get-setf-method form cl-macro-environment))) | ||
| 1657 | (list (car method) (nth 1 method) (nth 2 method) | ||
| 1658 | (cl-setf-make-apply (nth 3 method) (cadr func) (car method)) | ||
| 1659 | (cl-setf-make-apply (nth 4 method) (cadr func) (car method))))) | ||
| 1660 | |||
| 1661 | (defun cl-setf-make-apply (form func temps) | ||
| 1662 | (if (eq (car form) 'progn) | ||
| 1663 | (list* 'progn (cl-setf-make-apply (cadr form) func temps) (cddr form)) | ||
| 1664 | (or (equal (last form) (last temps)) | ||
| 1665 | (error "%s is not suitable for use with setf-of-apply" func)) | ||
| 1666 | (list* 'apply (list 'quote (car form)) (cdr form)))) | ||
| 1667 | |||
| 1668 | (define-setf-method nthcdr (n place) | ||
| 1669 | (let ((method (get-setf-method place cl-macro-environment)) | ||
| 1670 | (n-temp (gensym "--nthcdr-n--")) | ||
| 1671 | (store-temp (gensym "--nthcdr-store--"))) | ||
| 1672 | (list (cons n-temp (car method)) | ||
| 1673 | (cons n (nth 1 method)) | ||
| 1674 | (list store-temp) | ||
| 1675 | (list 'let (list (list (car (nth 2 method)) | ||
| 1676 | (list 'cl-set-nthcdr n-temp (nth 4 method) | ||
| 1677 | store-temp))) | ||
| 1678 | (nth 3 method) store-temp) | ||
| 1679 | (list 'nthcdr n-temp (nth 4 method))))) | ||
| 1680 | |||
| 1681 | (define-setf-method getf (place tag &optional def) | ||
| 1682 | (let ((method (get-setf-method place cl-macro-environment)) | ||
| 1683 | (tag-temp (gensym "--getf-tag--")) | ||
| 1684 | (def-temp (gensym "--getf-def--")) | ||
| 1685 | (store-temp (gensym "--getf-store--"))) | ||
| 1686 | (list (append (car method) (list tag-temp def-temp)) | ||
| 1687 | (append (nth 1 method) (list tag def)) | ||
| 1688 | (list store-temp) | ||
| 1689 | (list 'let (list (list (car (nth 2 method)) | ||
| 1690 | (list 'cl-set-getf (nth 4 method) | ||
| 1691 | tag-temp store-temp))) | ||
| 1692 | (nth 3 method) store-temp) | ||
| 1693 | (list 'getf (nth 4 method) tag-temp def-temp)))) | ||
| 1694 | |||
| 1695 | (define-setf-method substring (place from &optional to) | ||
| 1696 | (let ((method (get-setf-method place cl-macro-environment)) | ||
| 1697 | (from-temp (gensym "--substring-from--")) | ||
| 1698 | (to-temp (gensym "--substring-to--")) | ||
| 1699 | (store-temp (gensym "--substring-store--"))) | ||
| 1700 | (list (append (car method) (list from-temp to-temp)) | ||
| 1701 | (append (nth 1 method) (list from to)) | ||
| 1702 | (list store-temp) | ||
| 1703 | (list 'let (list (list (car (nth 2 method)) | ||
| 1704 | (list 'cl-set-substring (nth 4 method) | ||
| 1705 | from-temp to-temp store-temp))) | ||
| 1706 | (nth 3 method) store-temp) | ||
| 1707 | (list 'substring (nth 4 method) from-temp to-temp)))) | ||
| 1708 | |||
| 1709 | ;;; Getting and optimizing setf-methods. | ||
| 1710 | (defun get-setf-method (place &optional env) | ||
| 1711 | "Return a list of five values describing the setf-method for PLACE. | ||
| 1712 | PLACE may be any Lisp form which can appear as the PLACE argument to | ||
| 1713 | a macro like `setf' or `incf'." | ||
| 1714 | (if (symbolp place) | ||
| 1715 | (let ((temp (gensym "--setf--"))) | ||
| 1716 | (list nil nil (list temp) (list 'setq place temp) place)) | ||
| 1717 | (or (and (symbolp (car place)) | ||
| 1718 | (let* ((func (car place)) | ||
| 1719 | (name (symbol-name func)) | ||
| 1720 | (method (get func 'setf-method)) | ||
| 1721 | (case-fold-search nil)) | ||
| 1722 | (or (and method | ||
| 1723 | (let ((cl-macro-environment env)) | ||
| 1724 | (setq method (apply method (cdr place)))) | ||
| 1725 | (if (and (consp method) (= (length method) 5)) | ||
| 1726 | method | ||
| 1727 | (error "Setf-method for %s returns malformed method" | ||
| 1728 | func))) | ||
| 1729 | (and (string-match "\\`c[ad][ad][ad]?[ad]?r\\'" name) | ||
| 1730 | (get-setf-method (compiler-macroexpand place))) | ||
| 1731 | (and (eq func 'edebug-after) | ||
| 1732 | (get-setf-method (nth (1- (length place)) place) | ||
| 1733 | env))))) | ||
| 1734 | (if (eq place (setq place (macroexpand place env))) | ||
| 1735 | (if (and (symbolp (car place)) (fboundp (car place)) | ||
| 1736 | (symbolp (symbol-function (car place)))) | ||
| 1737 | (get-setf-method (cons (symbol-function (car place)) | ||
| 1738 | (cdr place)) env) | ||
| 1739 | (error "No setf-method known for %s" (car place))) | ||
| 1740 | (get-setf-method place env))))) | ||
| 1741 | |||
| 1742 | (defun cl-setf-do-modify (place opt-expr) | ||
| 1743 | (let* ((method (get-setf-method place cl-macro-environment)) | ||
| 1744 | (temps (car method)) (values (nth 1 method)) | ||
| 1745 | (lets nil) (subs nil) | ||
| 1746 | (optimize (and (not (eq opt-expr 'no-opt)) | ||
| 1747 | (or (and (not (eq opt-expr 'unsafe)) | ||
| 1748 | (cl-safe-expr-p opt-expr)) | ||
| 1749 | (cl-setf-simple-store-p (car (nth 2 method)) | ||
| 1750 | (nth 3 method))))) | ||
| 1751 | (simple (and optimize (consp place) (cl-simple-exprs-p (cdr place))))) | ||
| 1752 | (while values | ||
| 1753 | (if (or simple (cl-const-expr-p (car values))) | ||
| 1754 | (cl-push (cons (cl-pop temps) (cl-pop values)) subs) | ||
| 1755 | (cl-push (list (cl-pop temps) (cl-pop values)) lets))) | ||
| 1756 | (list (nreverse lets) | ||
| 1757 | (cons (car (nth 2 method)) (sublis subs (nth 3 method))) | ||
| 1758 | (sublis subs (nth 4 method))))) | ||
| 1759 | |||
| 1760 | (defun cl-setf-do-store (spec val) | ||
| 1761 | (let ((sym (car spec)) | ||
| 1762 | (form (cdr spec))) | ||
| 1763 | (if (or (cl-const-expr-p val) | ||
| 1764 | (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1)) | ||
| 1765 | (cl-setf-simple-store-p sym form)) | ||
| 1766 | (subst val sym form) | ||
| 1767 | (list 'let (list (list sym val)) form)))) | ||
| 1768 | |||
| 1769 | (defun cl-setf-simple-store-p (sym form) | ||
| 1770 | (and (consp form) (eq (cl-expr-contains form sym) 1) | ||
| 1771 | (eq (nth (1- (length form)) form) sym) | ||
| 1772 | (symbolp (car form)) (fboundp (car form)) | ||
| 1773 | (not (eq (car-safe (symbol-function (car form))) 'macro)))) | ||
| 1774 | |||
| 1775 | ;;; The standard modify macros. | ||
| 1776 | (defmacro setf (&rest args) | ||
| 1777 | "(setf PLACE VAL PLACE VAL ...): set each PLACE to the value of its VAL. | ||
| 1778 | This is a generalized version of `setq'; the PLACEs may be symbolic | ||
| 1779 | references such as (car x) or (aref x i), as well as plain symbols. | ||
| 1780 | For example, (setf (cadar x) y) is equivalent to (setcar (cdar x) y). | ||
| 1781 | The return value is the last VAL in the list." | ||
| 1782 | (if (cdr (cdr args)) | ||
| 1783 | (let ((sets nil)) | ||
| 1784 | (while args (cl-push (list 'setf (cl-pop args) (cl-pop args)) sets)) | ||
| 1785 | (cons 'progn (nreverse sets))) | ||
| 1786 | (if (symbolp (car args)) | ||
| 1787 | (and args (cons 'setq args)) | ||
| 1788 | (let* ((method (cl-setf-do-modify (car args) (nth 1 args))) | ||
| 1789 | (store (cl-setf-do-store (nth 1 method) (nth 1 args)))) | ||
| 1790 | (if (car method) (list 'let* (car method) store) store))))) | ||
| 1791 | |||
| 1792 | (defmacro psetf (&rest args) | ||
| 1793 | "(psetf PLACE VAL PLACE VAL ...): set PLACEs to the values VALs in parallel. | ||
| 1794 | This is like `setf', except that all VAL forms are evaluated (in order) | ||
| 1795 | before assigning any PLACEs to the corresponding values." | ||
| 1796 | (let ((p args) (simple t) (vars nil)) | ||
| 1797 | (while p | ||
| 1798 | (if (or (not (symbolp (car p))) (cl-expr-depends-p (nth 1 p) vars)) | ||
| 1799 | (setq simple nil)) | ||
| 1800 | (if (memq (car p) vars) | ||
| 1801 | (error "Destination duplicated in psetf: %s" (car p))) | ||
| 1802 | (cl-push (cl-pop p) vars) | ||
| 1803 | (or p (error "Odd number of arguments to psetf")) | ||
| 1804 | (cl-pop p)) | ||
| 1805 | (if simple | ||
| 1806 | (list 'progn (cons 'setf args) nil) | ||
| 1807 | (setq args (reverse args)) | ||
| 1808 | (let ((expr (list 'setf (cadr args) (car args)))) | ||
| 1809 | (while (setq args (cddr args)) | ||
| 1810 | (setq expr (list 'setf (cadr args) (list 'prog1 (car args) expr)))) | ||
| 1811 | (list 'progn expr nil))))) | ||
| 1812 | |||
| 1813 | (defun cl-do-pop (place) | ||
| 1814 | (if (cl-simple-expr-p place) | ||
| 1815 | (list 'prog1 (list 'car place) (list 'setf place (list 'cdr place))) | ||
| 1816 | (let* ((method (cl-setf-do-modify place t)) | ||
| 1817 | (temp (gensym "--pop--"))) | ||
| 1818 | (list 'let* | ||
| 1819 | (append (car method) | ||
| 1820 | (list (list temp (nth 2 method)))) | ||
| 1821 | (list 'prog1 | ||
| 1822 | (list 'car temp) | ||
| 1823 | (cl-setf-do-store (nth 1 method) (list 'cdr temp))))))) | ||
| 1824 | |||
| 1825 | (defmacro remf (place tag) | ||
| 1826 | "(remf PLACE TAG): remove TAG from property list PLACE. | ||
| 1827 | PLACE may be a symbol, or any generalized variable allowed by `setf'. | ||
| 1828 | The form returns true if TAG was found and removed, nil otherwise." | ||
| 1829 | (let* ((method (cl-setf-do-modify place t)) | ||
| 1830 | (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--"))) | ||
| 1831 | (val-temp (and (not (cl-simple-expr-p place)) | ||
| 1832 | (gensym "--remf-place--"))) | ||
| 1833 | (ttag (or tag-temp tag)) | ||
| 1834 | (tval (or val-temp (nth 2 method)))) | ||
| 1835 | (list 'let* | ||
| 1836 | (append (car method) | ||
| 1837 | (and val-temp (list (list val-temp (nth 2 method)))) | ||
| 1838 | (and tag-temp (list (list tag-temp tag)))) | ||
| 1839 | (list 'if (list 'eq ttag (list 'car tval)) | ||
| 1840 | (list 'progn | ||
| 1841 | (cl-setf-do-store (nth 1 method) (list 'cddr tval)) | ||
| 1842 | t) | ||
| 1843 | (list 'cl-do-remf tval ttag))))) | ||
| 1844 | |||
| 1845 | (defmacro shiftf (place &rest args) | ||
| 1846 | "(shiftf PLACE PLACE... VAL): shift left among PLACEs. | ||
| 1847 | Example: (shiftf A B C) sets A to B, B to C, and returns the old A. | ||
| 1848 | Each PLACE may be a symbol, or any generalized variable allowed by `setf'." | ||
| 1849 | (if (not (memq nil (mapcar 'symbolp (butlast (cons place args))))) | ||
| 1850 | (list* 'prog1 place | ||
| 1851 | (let ((sets nil)) | ||
| 1852 | (while args | ||
| 1853 | (cl-push (list 'setq place (car args)) sets) | ||
| 1854 | (setq place (cl-pop args))) | ||
| 1855 | (nreverse sets))) | ||
| 1856 | (let* ((places (reverse (cons place args))) | ||
| 1857 | (form (cl-pop places))) | ||
| 1858 | (while places | ||
| 1859 | (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) | ||
| 1860 | (setq form (list 'let* (car method) | ||
| 1861 | (list 'prog1 (nth 2 method) | ||
| 1862 | (cl-setf-do-store (nth 1 method) form)))))) | ||
| 1863 | form))) | ||
| 1864 | |||
| 1865 | (defmacro rotatef (&rest args) | ||
| 1866 | "(rotatef PLACE...): rotate left among PLACEs. | ||
| 1867 | Example: (rotatef A B C) sets A to B, B to C, and C to A. It returns nil. | ||
| 1868 | Each PLACE may be a symbol, or any generalized variable allowed by `setf'." | ||
| 1869 | (if (not (memq nil (mapcar 'symbolp args))) | ||
| 1870 | (and (cdr args) | ||
| 1871 | (let ((sets nil) | ||
| 1872 | (first (car args))) | ||
| 1873 | (while (cdr args) | ||
| 1874 | (setq sets (nconc sets (list (cl-pop args) (car args))))) | ||
| 1875 | (nconc (list 'psetf) sets (list (car args) first)))) | ||
| 1876 | (let* ((places (reverse args)) | ||
| 1877 | (temp (gensym "--rotatef--")) | ||
| 1878 | (form temp)) | ||
| 1879 | (while (cdr places) | ||
| 1880 | (let ((method (cl-setf-do-modify (cl-pop places) 'unsafe))) | ||
| 1881 | (setq form (list 'let* (car method) | ||
| 1882 | (list 'prog1 (nth 2 method) | ||
| 1883 | (cl-setf-do-store (nth 1 method) form)))))) | ||
| 1884 | (let ((method (cl-setf-do-modify (car places) 'unsafe))) | ||
| 1885 | (list 'let* (append (car method) (list (list temp (nth 2 method)))) | ||
| 1886 | (cl-setf-do-store (nth 1 method) form) nil))))) | ||
| 1887 | |||
| 1888 | (defmacro letf (bindings &rest body) | ||
| 1889 | "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. | ||
| 1890 | This is the analogue of `let', but with generalized variables (in the | ||
| 1891 | sense of `setf') for the PLACEs. Each PLACE is set to the corresponding | ||
| 1892 | VALUE, then the BODY forms are executed. On exit, either normally or | ||
| 1893 | because of a `throw' or error, the PLACEs are set back to their original | ||
| 1894 | values. Note that this macro is *not* available in Common Lisp. | ||
| 1895 | As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', | ||
| 1896 | the PLACE is not modified before executing BODY." | ||
| 1897 | (if (and (not (cdr bindings)) (cdar bindings) (symbolp (caar bindings))) | ||
| 1898 | (list* 'let bindings body) | ||
| 1899 | (let ((lets nil) (sets nil) | ||
| 1900 | (unsets nil) (rev (reverse bindings))) | ||
| 1901 | (while rev | ||
| 1902 | (let* ((place (if (symbolp (caar rev)) | ||
| 1903 | (list 'symbol-value (list 'quote (caar rev))) | ||
| 1904 | (caar rev))) | ||
| 1905 | (value (cadar rev)) | ||
| 1906 | (method (cl-setf-do-modify place 'no-opt)) | ||
| 1907 | (save (gensym "--letf-save--")) | ||
| 1908 | (bound (and (memq (car place) '(symbol-value symbol-function)) | ||
| 1909 | (gensym "--letf-bound--"))) | ||
| 1910 | (temp (and (not (cl-const-expr-p value)) (cdr bindings) | ||
| 1911 | (gensym "--letf-val--")))) | ||
| 1912 | (setq lets (nconc (car method) | ||
| 1913 | (if bound | ||
| 1914 | (list (list bound | ||
| 1915 | (list (if (eq (car place) | ||
| 1916 | 'symbol-value) | ||
| 1917 | 'boundp 'fboundp) | ||
| 1918 | (nth 1 (nth 2 method)))) | ||
| 1919 | (list save (list 'and bound | ||
| 1920 | (nth 2 method)))) | ||
| 1921 | (list (list save (nth 2 method)))) | ||
| 1922 | (and temp (list (list temp value))) | ||
| 1923 | lets) | ||
| 1924 | body (list | ||
| 1925 | (list 'unwind-protect | ||
| 1926 | (cons 'progn | ||
| 1927 | (if (cdr (car rev)) | ||
| 1928 | (cons (cl-setf-do-store (nth 1 method) | ||
| 1929 | (or temp value)) | ||
| 1930 | body) | ||
| 1931 | body)) | ||
| 1932 | (if bound | ||
| 1933 | (list 'if bound | ||
| 1934 | (cl-setf-do-store (nth 1 method) save) | ||
| 1935 | (list (if (eq (car place) 'symbol-value) | ||
| 1936 | 'makunbound 'fmakunbound) | ||
| 1937 | (nth 1 (nth 2 method)))) | ||
| 1938 | (cl-setf-do-store (nth 1 method) save)))) | ||
| 1939 | rev (cdr rev)))) | ||
| 1940 | (list* 'let* lets body)))) | ||
| 1941 | |||
| 1942 | (defmacro letf* (bindings &rest body) | ||
| 1943 | "(letf* ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. | ||
| 1944 | This is the analogue of `let*', but with generalized variables (in the | ||
| 1945 | sense of `setf') for the PLACEs. Each PLACE is set to the corresponding | ||
| 1946 | VALUE, then the BODY forms are executed. On exit, either normally or | ||
| 1947 | because of a `throw' or error, the PLACEs are set back to their original | ||
| 1948 | values. Note that this macro is *not* available in Common Lisp. | ||
| 1949 | As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)', | ||
| 1950 | the PLACE is not modified before executing BODY." | ||
| 1951 | (if (null bindings) | ||
| 1952 | (cons 'progn body) | ||
| 1953 | (setq bindings (reverse bindings)) | ||
| 1954 | (while bindings | ||
| 1955 | (setq body (list (list* 'letf (list (cl-pop bindings)) body)))) | ||
| 1956 | (car body))) | ||
| 1957 | |||
| 1958 | (defmacro callf (func place &rest args) | ||
| 1959 | "(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). | ||
| 1960 | FUNC should be an unquoted function name. PLACE may be a symbol, | ||
| 1961 | or any generalized variable allowed by `setf'." | ||
| 1962 | (let* ((method (cl-setf-do-modify place (cons 'list args))) | ||
| 1963 | (rargs (cons (nth 2 method) args))) | ||
| 1964 | (list 'let* (car method) | ||
| 1965 | (cl-setf-do-store (nth 1 method) | ||
| 1966 | (if (symbolp func) (cons func rargs) | ||
| 1967 | (list* 'funcall (list 'function func) | ||
| 1968 | rargs)))))) | ||
| 1969 | |||
| 1970 | (defmacro callf2 (func arg1 place &rest args) | ||
| 1971 | "(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). | ||
| 1972 | Like `callf', but PLACE is the second argument of FUNC, not the first." | ||
| 1973 | (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func)) | ||
| 1974 | (list 'setf place (list* func arg1 place args)) | ||
| 1975 | (let* ((method (cl-setf-do-modify place (cons 'list args))) | ||
| 1976 | (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--"))) | ||
| 1977 | (rargs (list* (or temp arg1) (nth 2 method) args))) | ||
| 1978 | (list 'let* (append (and temp (list (list temp arg1))) (car method)) | ||
| 1979 | (cl-setf-do-store (nth 1 method) | ||
| 1980 | (if (symbolp func) (cons func rargs) | ||
| 1981 | (list* 'funcall (list 'function func) | ||
| 1982 | rargs))))))) | ||
| 1983 | |||
| 1984 | (defmacro define-modify-macro (name arglist func &optional doc) | ||
| 1985 | "(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. | ||
| 1986 | If NAME is called, it combines its PLACE argument with the other arguments | ||
| 1987 | from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" | ||
| 1988 | (if (memq '&key arglist) (error "&key not allowed in define-modify-macro")) | ||
| 1989 | (let ((place (gensym "--place--"))) | ||
| 1990 | (list 'defmacro* name (cons place arglist) doc | ||
| 1991 | (list* (if (memq '&rest arglist) 'list* 'list) | ||
| 1992 | '(quote callf) (list 'quote func) place | ||
| 1993 | (cl-arglist-args arglist))))) | ||
| 1994 | |||
| 1995 | |||
| 1996 | ;;; Structures. | ||
| 1997 | |||
| 1998 | (defmacro defstruct (struct &rest descs) | ||
| 1999 | "(defstruct (NAME OPTIONS...) (SLOT SLOT-OPTS...)...): define a struct type. | ||
| 2000 | This macro defines a new Lisp data type called NAME, which contains data | ||
| 2001 | stored in SLOTs. This defines a `make-NAME' constructor, a `copy-NAME' | ||
| 2002 | copier, a `NAME-p' predicate, and setf-able `NAME-SLOT' accessors." | ||
| 2003 | (let* ((name (if (consp struct) (car struct) struct)) | ||
| 2004 | (opts (cdr-safe struct)) | ||
| 2005 | (slots nil) | ||
| 2006 | (defaults nil) | ||
| 2007 | (conc-name (concat (symbol-name name) "-")) | ||
| 2008 | (constructor (intern (format "make-%s" name))) | ||
| 2009 | (constrs nil) | ||
| 2010 | (copier (intern (format "copy-%s" name))) | ||
| 2011 | (predicate (intern (format "%s-p" name))) | ||
| 2012 | (print-func nil) (print-auto nil) | ||
| 2013 | (safety (if (cl-compiling-file) cl-optimize-safety 3)) | ||
| 2014 | (include nil) | ||
| 2015 | (tag (intern (format "cl-struct-%s" name))) | ||
| 2016 | (tag-symbol (intern (format "cl-struct-%s-tags" name))) | ||
| 2017 | (include-descs nil) | ||
| 2018 | (include-tag-symbol nil) | ||
| 2019 | (side-eff nil) | ||
| 2020 | (type nil) | ||
| 2021 | (named nil) | ||
| 2022 | (forms nil) | ||
| 2023 | pred-form pred-check) | ||
| 2024 | (if (stringp (car descs)) | ||
| 2025 | (cl-push (list 'put (list 'quote name) '(quote structure-documentation) | ||
| 2026 | (cl-pop descs)) forms)) | ||
| 2027 | (setq descs (cons '(cl-tag-slot) | ||
| 2028 | (mapcar (function (lambda (x) (if (consp x) x (list x)))) | ||
| 2029 | descs))) | ||
| 2030 | (while opts | ||
| 2031 | (let ((opt (if (consp (car opts)) (caar opts) (car opts))) | ||
| 2032 | (args (cdr-safe (cl-pop opts)))) | ||
| 2033 | (cond ((eq opt ':conc-name) | ||
| 2034 | (if args | ||
| 2035 | (setq conc-name (if (car args) | ||
| 2036 | (symbol-name (car args)) "")))) | ||
| 2037 | ((eq opt ':constructor) | ||
| 2038 | (if (cdr args) | ||
| 2039 | (cl-push args constrs) | ||
| 2040 | (if args (setq constructor (car args))))) | ||
| 2041 | ((eq opt ':copier) | ||
| 2042 | (if args (setq copier (car args)))) | ||
| 2043 | ((eq opt ':predicate) | ||
| 2044 | (if args (setq predicate (car args)))) | ||
| 2045 | ((eq opt ':include) | ||
| 2046 | (setq include (car args) | ||
| 2047 | include-descs (mapcar (function | ||
| 2048 | (lambda (x) | ||
| 2049 | (if (consp x) x (list x)))) | ||
| 2050 | (cdr args)) | ||
| 2051 | include-tag-symbol (intern (format "cl-struct-%s-tags" | ||
| 2052 | include)))) | ||
| 2053 | ((eq opt ':print-function) | ||
| 2054 | (setq print-func (car args))) | ||
| 2055 | ((eq opt ':type) | ||
| 2056 | (setq type (car args))) | ||
| 2057 | ((eq opt ':named) | ||
| 2058 | (setq named t)) | ||
| 2059 | ((eq opt ':initial-offset) | ||
| 2060 | (setq descs (nconc (make-list (car args) '(cl-skip-slot)) | ||
| 2061 | descs))) | ||
| 2062 | (t | ||
| 2063 | (error "Slot option %s unrecognized" opt))))) | ||
| 2064 | (if print-func | ||
| 2065 | (setq print-func (list 'progn | ||
| 2066 | (list 'funcall (list 'function print-func) | ||
| 2067 | 'cl-x 'cl-s 'cl-n) t)) | ||
| 2068 | (or type (and include (not (get include 'cl-struct-print))) | ||
| 2069 | (setq print-auto t | ||
| 2070 | print-func (and (or (not (or include type)) (null print-func)) | ||
| 2071 | (list 'progn | ||
| 2072 | (list 'princ (format "#S(%s" name) | ||
| 2073 | 'cl-s)))))) | ||
| 2074 | (if include | ||
| 2075 | (let ((inc-type (get include 'cl-struct-type)) | ||
| 2076 | (old-descs (get include 'cl-struct-slots))) | ||
| 2077 | (or inc-type (error "%s is not a struct name" include)) | ||
| 2078 | (and type (not (eq (car inc-type) type)) | ||
| 2079 | (error ":type disagrees with :include for %s" name)) | ||
| 2080 | (while include-descs | ||
| 2081 | (setcar (memq (or (assq (caar include-descs) old-descs) | ||
| 2082 | (error "No slot %s in included struct %s" | ||
| 2083 | (caar include-descs) include)) | ||
| 2084 | old-descs) | ||
| 2085 | (cl-pop include-descs))) | ||
| 2086 | (setq descs (append old-descs (delq (assq 'cl-tag-slot descs) descs)) | ||
| 2087 | type (car inc-type) | ||
| 2088 | named (assq 'cl-tag-slot descs)) | ||
| 2089 | (if (cadr inc-type) (setq tag name named t)) | ||
| 2090 | (cl-push (list 'pushnew (list 'quote tag) include-tag-symbol) | ||
| 2091 | forms)) | ||
| 2092 | (if type | ||
| 2093 | (progn | ||
| 2094 | (or (memq type '(vector list)) | ||
| 2095 | (error "Illegal :type specifier: %s" type)) | ||
| 2096 | (if named (setq tag name))) | ||
| 2097 | (setq type 'vector named 'true))) | ||
| 2098 | (or named (setq descs (delq (assq 'cl-tag-slot descs) descs))) | ||
| 2099 | (cl-push (list 'defvar tag-symbol) forms) | ||
| 2100 | (setq pred-form (and named | ||
| 2101 | (let ((pos (- (length descs) | ||
| 2102 | (length (memq (assq 'cl-tag-slot descs) | ||
| 2103 | descs))))) | ||
| 2104 | (if (eq type 'vector) | ||
| 2105 | (list 'and '(vectorp cl-x) | ||
| 2106 | (list '>= '(length cl-x) (length descs)) | ||
| 2107 | (list 'memq (list 'aref 'cl-x pos) | ||
| 2108 | tag-symbol)) | ||
| 2109 | (if (= pos 0) | ||
| 2110 | (list 'memq '(car-safe cl-x) tag-symbol) | ||
| 2111 | (list 'and '(consp cl-x) | ||
| 2112 | (list 'memq (list 'nth pos 'cl-x) | ||
| 2113 | tag-symbol)))))) | ||
| 2114 | pred-check (and pred-form (> safety 0) | ||
| 2115 | (if (and (eq (caadr pred-form) 'vectorp) | ||
| 2116 | (= safety 1)) | ||
| 2117 | (cons 'and (cdddr pred-form)) pred-form))) | ||
| 2118 | (let ((pos 0) (descp descs)) | ||
| 2119 | (while descp | ||
| 2120 | (let* ((desc (cl-pop descp)) | ||
| 2121 | (slot (car desc))) | ||
| 2122 | (if (memq slot '(cl-tag-slot cl-skip-slot)) | ||
| 2123 | (progn | ||
| 2124 | (cl-push nil slots) | ||
| 2125 | (cl-push (and (eq slot 'cl-tag-slot) (list 'quote tag)) | ||
| 2126 | defaults)) | ||
| 2127 | (if (assq slot descp) | ||
| 2128 | (error "Duplicate slots named %s in %s" slot name)) | ||
| 2129 | (let ((accessor (intern (format "%s%s" conc-name slot)))) | ||
| 2130 | (cl-push slot slots) | ||
| 2131 | (cl-push (nth 1 desc) defaults) | ||
| 2132 | (cl-push (list* | ||
| 2133 | 'defsubst* accessor '(cl-x) | ||
| 2134 | (append | ||
| 2135 | (and pred-check | ||
| 2136 | (list (list 'or pred-check | ||
| 2137 | (list 'error | ||
| 2138 | (format "%s accessing a non-%s" | ||
| 2139 | accessor name) | ||
| 2140 | 'cl-x)))) | ||
| 2141 | (list (if (eq type 'vector) (list 'aref 'cl-x pos) | ||
| 2142 | (if (= pos 0) '(car cl-x) | ||
| 2143 | (list 'nth pos 'cl-x)))))) forms) | ||
| 2144 | (cl-push (cons accessor t) side-eff) | ||
| 2145 | (cl-push (list 'define-setf-method accessor '(cl-x) | ||
| 2146 | (if (cadr (memq ':read-only (cddr desc))) | ||
| 2147 | (list 'error (format "%s is a read-only slot" | ||
| 2148 | accessor)) | ||
| 2149 | (list 'cl-struct-setf-expander 'cl-x | ||
| 2150 | (list 'quote name) (list 'quote accessor) | ||
| 2151 | (and pred-check (list 'quote pred-check)) | ||
| 2152 | pos))) | ||
| 2153 | forms) | ||
| 2154 | (if print-auto | ||
| 2155 | (nconc print-func | ||
| 2156 | (list (list 'princ (format " %s" slot) 'cl-s) | ||
| 2157 | (list 'prin1 (list accessor 'cl-x) 'cl-s))))))) | ||
| 2158 | (setq pos (1+ pos)))) | ||
| 2159 | (setq slots (nreverse slots) | ||
| 2160 | defaults (nreverse defaults)) | ||
| 2161 | (and predicate pred-form | ||
| 2162 | (progn (cl-push (list 'defsubst* predicate '(cl-x) | ||
| 2163 | (if (eq (car pred-form) 'and) | ||
| 2164 | (append pred-form '(t)) | ||
| 2165 | (list 'and pred-form t))) forms) | ||
| 2166 | (cl-push (cons predicate 'error-free) side-eff))) | ||
| 2167 | (and copier | ||
| 2168 | (progn (cl-push (list 'defun copier '(x) '(copy-sequence x)) forms) | ||
| 2169 | (cl-push (cons copier t) side-eff))) | ||
| 2170 | (if constructor | ||
| 2171 | (cl-push (list constructor | ||
| 2172 | (cons '&key (delq nil (copy-sequence slots)))) | ||
| 2173 | constrs)) | ||
| 2174 | (while constrs | ||
| 2175 | (let* ((name (caar constrs)) | ||
| 2176 | (args (cadr (cl-pop constrs))) | ||
| 2177 | (anames (cl-arglist-args args)) | ||
| 2178 | (make (mapcar* (function (lambda (s d) (if (memq s anames) s d))) | ||
| 2179 | slots defaults))) | ||
| 2180 | (cl-push (list 'defsubst* name | ||
| 2181 | (list* '&cl-defs (list 'quote (cons nil descs)) args) | ||
| 2182 | (cons type make)) forms) | ||
| 2183 | (if (cl-safe-expr-p (cons 'progn (mapcar 'second descs))) | ||
| 2184 | (cl-push (cons name t) side-eff)))) | ||
| 2185 | (if print-auto (nconc print-func (list '(princ ")" cl-s) t))) | ||
| 2186 | (if print-func | ||
| 2187 | (cl-push (list 'push | ||
| 2188 | (list 'function | ||
| 2189 | (list 'lambda '(cl-x cl-s cl-n) | ||
| 2190 | (list 'and pred-form print-func))) | ||
| 2191 | 'custom-print-functions) forms)) | ||
| 2192 | (cl-push (list 'setq tag-symbol (list 'list (list 'quote tag))) forms) | ||
| 2193 | (cl-push (list* 'eval-when '(compile load eval) | ||
| 2194 | (list 'put (list 'quote name) '(quote cl-struct-slots) | ||
| 2195 | (list 'quote descs)) | ||
| 2196 | (list 'put (list 'quote name) '(quote cl-struct-type) | ||
| 2197 | (list 'quote (list type (eq named t)))) | ||
| 2198 | (list 'put (list 'quote name) '(quote cl-struct-print) | ||
| 2199 | print-auto) | ||
| 2200 | (mapcar (function (lambda (x) | ||
| 2201 | (list 'put (list 'quote (car x)) | ||
| 2202 | '(quote side-effect-free) | ||
| 2203 | (list 'quote (cdr x))))) | ||
| 2204 | side-eff)) | ||
| 2205 | forms) | ||
| 2206 | (cons 'progn (nreverse (cons (list 'quote name) forms))))) | ||
| 2207 | |||
| 2208 | (defun cl-struct-setf-expander (x name accessor pred-form pos) | ||
| 2209 | (let* ((temp (gensym "--x--")) (store (gensym "--store--"))) | ||
| 2210 | (list (list temp) (list x) (list store) | ||
| 2211 | (append '(progn) | ||
| 2212 | (and pred-form | ||
| 2213 | (list (list 'or (subst temp 'cl-x pred-form) | ||
| 2214 | (list 'error | ||
| 2215 | (format | ||
| 2216 | "%s storing a non-%s" accessor name) | ||
| 2217 | temp)))) | ||
| 2218 | (list (if (eq (car (get name 'cl-struct-type)) 'vector) | ||
| 2219 | (list 'aset temp pos store) | ||
| 2220 | (list 'setcar | ||
| 2221 | (if (<= pos 5) | ||
| 2222 | (let ((xx temp)) | ||
| 2223 | (while (>= (setq pos (1- pos)) 0) | ||
| 2224 | (setq xx (list 'cdr xx))) | ||
| 2225 | xx) | ||
| 2226 | (list 'nthcdr pos temp)) | ||
| 2227 | store)))) | ||
| 2228 | (list accessor temp)))) | ||
| 2229 | |||
| 2230 | |||
| 2231 | ;;; Types and assertions. | ||
| 2232 | |||
| 2233 | (defmacro deftype (name args &rest body) | ||
| 2234 | "(deftype NAME ARGLIST BODY...): define NAME as a new data type. | ||
| 2235 | The type name can then be used in `typecase', `check-type', etc." | ||
| 2236 | (list 'eval-when '(compile load eval) | ||
| 2237 | (cl-transform-function-property | ||
| 2238 | name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) args) body)))) | ||
| 2239 | |||
| 2240 | (defun cl-make-type-test (val type) | ||
| 2241 | (if (memq type '(character string-char)) (setq type '(integer 0 255))) | ||
| 2242 | (if (symbolp type) | ||
| 2243 | (cond ((get type 'cl-deftype-handler) | ||
| 2244 | (cl-make-type-test val (funcall (get type 'cl-deftype-handler)))) | ||
| 2245 | ((memq type '(nil t)) type) | ||
| 2246 | ((eq type 'null) (list 'null val)) | ||
| 2247 | ((eq type 'float) (list 'floatp-safe val)) | ||
| 2248 | ((eq type 'real) (list 'numberp val)) | ||
| 2249 | ((eq type 'fixnum) (list 'integerp val)) | ||
| 2250 | (t | ||
| 2251 | (let* ((name (symbol-name type)) | ||
| 2252 | (namep (intern (concat name "p")))) | ||
| 2253 | (if (fboundp namep) (list namep val) | ||
| 2254 | (list (intern (concat name "-p")) val))))) | ||
| 2255 | (cond ((get (car type) 'cl-deftype-handler) | ||
| 2256 | (cl-make-type-test val (apply (get (car type) 'cl-deftype-handler) | ||
| 2257 | (cdr type)))) | ||
| 2258 | ((memq (car-safe type) '(integer float real number)) | ||
| 2259 | (delq t (list 'and (cl-make-type-test val (car type)) | ||
| 2260 | (if (memq (cadr type) '(* nil)) t | ||
| 2261 | (if (consp (cadr type)) (list '> val (caadr type)) | ||
| 2262 | (list '>= val (cadr type)))) | ||
| 2263 | (if (memq (caddr type) '(* nil)) t | ||
| 2264 | (if (consp (caddr type)) (list '< val (caaddr type)) | ||
| 2265 | (list '<= val (caddr type))))))) | ||
| 2266 | ((memq (car-safe type) '(and or not)) | ||
| 2267 | (cons (car type) | ||
| 2268 | (mapcar (function (lambda (x) (cl-make-type-test val x))) | ||
| 2269 | (cdr type)))) | ||
| 2270 | ((memq (car-safe type) '(member member*)) | ||
| 2271 | (list 'and (list 'member* val (list 'quote (cdr type))) t)) | ||
| 2272 | ((eq (car-safe type) 'satisfies) (list (cadr type) val)) | ||
| 2273 | (t (error "Bad type spec: %s" type))))) | ||
| 2274 | |||
| 2275 | (defun typep (val type) ; See compiler macro below. | ||
| 2276 | "Check that OBJECT is of type TYPE. | ||
| 2277 | TYPE is a Common Lisp-style type specifier." | ||
| 2278 | (eval (cl-make-type-test 'val type))) | ||
| 2279 | |||
| 2280 | (defmacro check-type (form type &optional string) | ||
| 2281 | "Verify that FORM is of type TYPE; signal an error if not. | ||
| 2282 | STRING is an optional description of the desired type." | ||
| 2283 | (and (or (not (cl-compiling-file)) | ||
| 2284 | (< cl-optimize-speed 3) (= cl-optimize-safety 3)) | ||
| 2285 | (let* ((temp (if (cl-simple-expr-p form 3) form (gensym))) | ||
| 2286 | (body (list 'or (cl-make-type-test temp type) | ||
| 2287 | (list 'signal '(quote wrong-type-argument) | ||
| 2288 | (list 'list (or string (list 'quote type)) | ||
| 2289 | temp (list 'quote form)))))) | ||
| 2290 | (if (eq temp form) (list 'progn body nil) | ||
| 2291 | (list 'let (list (list temp form)) body nil))))) | ||
| 2292 | |||
| 2293 | (defmacro assert (form &optional show-args string &rest args) | ||
| 2294 | "Verify that FORM returns non-nil; signal an error if not. | ||
| 2295 | Second arg SHOW-ARGS means to include arguments of FORM in message. | ||
| 2296 | Other args STRING and ARGS... are arguments to be passed to `error'. | ||
| 2297 | They are not evaluated unless the assertion fails. If STRING is | ||
| 2298 | omitted, a default message listing FORM itself is used." | ||
| 2299 | (and (or (not (cl-compiling-file)) | ||
| 2300 | (< cl-optimize-speed 3) (= cl-optimize-safety 3)) | ||
| 2301 | (let ((sargs (and show-args (delq nil (mapcar | ||
| 2302 | (function | ||
| 2303 | (lambda (x) | ||
| 2304 | (and (not (cl-const-expr-p x)) | ||
| 2305 | x))) (cdr form)))))) | ||
| 2306 | (list 'progn | ||
| 2307 | (list 'or form | ||
| 2308 | (if string | ||
| 2309 | (list* 'error string (append sargs args)) | ||
| 2310 | (list 'signal '(quote cl-assertion-failed) | ||
| 2311 | (list* 'list (list 'quote form) sargs)))) | ||
| 2312 | nil)))) | ||
| 2313 | |||
| 2314 | (defmacro ignore-errors (&rest body) | ||
| 2315 | "Execute FORMS; if an error occurs, return nil. | ||
| 2316 | Otherwise, return result of last FORM." | ||
| 2317 | (let ((err (gensym))) | ||
| 2318 | (list 'condition-case err (cons 'progn body) '(error nil)))) | ||
| 2319 | |||
| 2320 | |||
| 2321 | ;;; Some predicates for analyzing Lisp forms. These are used by various | ||
| 2322 | ;;; macro expanders to optimize the results in certain common cases. | ||
| 2323 | |||
| 2324 | (defconst cl-simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max | ||
| 2325 | car-safe cdr-safe progn prog1 prog2)) | ||
| 2326 | (defconst cl-safe-funcs '(* / % length memq list vector vectorp | ||
| 2327 | < > <= >= = error)) | ||
| 2328 | |||
| 2329 | ;;; Check if no side effects, and executes quickly. | ||
| 2330 | (defun cl-simple-expr-p (x &optional size) | ||
| 2331 | (or size (setq size 10)) | ||
| 2332 | (if (and (consp x) (not (memq (car x) '(quote function function*)))) | ||
| 2333 | (and (symbolp (car x)) | ||
| 2334 | (or (memq (car x) cl-simple-funcs) | ||
| 2335 | (get (car x) 'side-effect-free)) | ||
| 2336 | (progn | ||
| 2337 | (setq size (1- size)) | ||
| 2338 | (while (and (setq x (cdr x)) | ||
| 2339 | (setq size (cl-simple-expr-p (car x) size)))) | ||
| 2340 | (and (null x) (>= size 0) size))) | ||
| 2341 | (and (> size 0) (1- size)))) | ||
| 2342 | |||
| 2343 | (defun cl-simple-exprs-p (xs) | ||
| 2344 | (while (and xs (cl-simple-expr-p (car xs))) | ||
| 2345 | (setq xs (cdr xs))) | ||
| 2346 | (not xs)) | ||
| 2347 | |||
| 2348 | ;;; Check if no side effects. | ||
| 2349 | (defun cl-safe-expr-p (x) | ||
| 2350 | (or (not (and (consp x) (not (memq (car x) '(quote function function*))))) | ||
| 2351 | (and (symbolp (car x)) | ||
| 2352 | (or (memq (car x) cl-simple-funcs) | ||
| 2353 | (memq (car x) cl-safe-funcs) | ||
| 2354 | (get (car x) 'side-effect-free)) | ||
| 2355 | (progn | ||
| 2356 | (while (and (setq x (cdr x)) (cl-safe-expr-p (car x)))) | ||
| 2357 | (null x))))) | ||
| 2358 | |||
| 2359 | ;;; Check if constant (i.e., no side effects or dependencies). | ||
| 2360 | (defun cl-const-expr-p (x) | ||
| 2361 | (cond ((consp x) | ||
| 2362 | (or (eq (car x) 'quote) | ||
| 2363 | (and (memq (car x) '(function function*)) | ||
| 2364 | (or (symbolp (nth 1 x)) | ||
| 2365 | (and (eq (car-safe (nth 1 x)) 'lambda) 'func))))) | ||
| 2366 | ((symbolp x) (and (memq x '(nil t)) t)) | ||
| 2367 | (t t))) | ||
| 2368 | |||
| 2369 | (defun cl-const-exprs-p (xs) | ||
| 2370 | (while (and xs (cl-const-expr-p (car xs))) | ||
| 2371 | (setq xs (cdr xs))) | ||
| 2372 | (not xs)) | ||
| 2373 | |||
| 2374 | (defun cl-const-expr-val (x) | ||
| 2375 | (and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x))) | ||
| 2376 | |||
| 2377 | (defun cl-expr-access-order (x v) | ||
| 2378 | (if (cl-const-expr-p x) v | ||
| 2379 | (if (consp x) | ||
| 2380 | (progn | ||
| 2381 | (while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v))) | ||
| 2382 | v) | ||
| 2383 | (if (eq x (car v)) (cdr v) '(t))))) | ||
| 2384 | |||
| 2385 | ;;; Count number of times X refers to Y. Return NIL for 0 times. | ||
| 2386 | (defun cl-expr-contains (x y) | ||
| 2387 | (cond ((equal y x) 1) | ||
| 2388 | ((and (consp x) (not (memq (car-safe x) '(quote function function*)))) | ||
| 2389 | (let ((sum 0)) | ||
| 2390 | (while x | ||
| 2391 | (setq sum (+ sum (or (cl-expr-contains (cl-pop x) y) 0)))) | ||
| 2392 | (and (> sum 0) sum))) | ||
| 2393 | (t nil))) | ||
| 2394 | |||
| 2395 | (defun cl-expr-contains-any (x y) | ||
| 2396 | (while (and y (not (cl-expr-contains x (car y)))) (cl-pop y)) | ||
| 2397 | y) | ||
| 2398 | |||
| 2399 | ;;; Check whether X may depend on any of the symbols in Y. | ||
| 2400 | (defun cl-expr-depends-p (x y) | ||
| 2401 | (and (not (cl-const-expr-p x)) | ||
| 2402 | (or (not (cl-safe-expr-p x)) (cl-expr-contains-any x y)))) | ||
| 2403 | |||
| 2404 | |||
| 2405 | ;;; Compiler macros. | ||
| 2406 | |||
| 2407 | (defmacro define-compiler-macro (func args &rest body) | ||
| 2408 | "(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. | ||
| 2409 | This is like `defmacro', but macro expansion occurs only if the call to | ||
| 2410 | FUNC is compiled (i.e., not interpreted). Compiler macros should be used | ||
| 2411 | for optimizing the way calls to FUNC are compiled; the form returned by | ||
| 2412 | BODY should do the same thing as a call to the normal function called | ||
| 2413 | FUNC, though possibly more efficiently. Note that, like regular macros, | ||
| 2414 | compiler macros are expanded repeatedly until no further expansions are | ||
| 2415 | possible. Unlike regular macros, BODY can decide to \"punt\" and leave the | ||
| 2416 | original function call alone by declaring an initial `&whole foo' parameter | ||
| 2417 | and then returning foo." | ||
| 2418 | (let ((p (if (listp args) args (list '&rest args))) (res nil)) | ||
| 2419 | (while (consp p) (cl-push (cl-pop p) res)) | ||
| 2420 | (setq args (nreverse res)) (setcdr res (and p (list '&rest p)))) | ||
| 2421 | (list 'eval-when '(compile load eval) | ||
| 2422 | (cl-transform-function-property | ||
| 2423 | func 'cl-compiler-macro | ||
| 2424 | (cons (if (memq '&whole args) (delq '&whole args) | ||
| 2425 | (cons '--cl-whole-arg-- args)) body)) | ||
| 2426 | (list 'or (list 'get (list 'quote func) '(quote byte-compile)) | ||
| 2427 | (list 'put (list 'quote func) '(quote byte-compile) | ||
| 2428 | '(quote cl-byte-compile-compiler-macro))))) | ||
| 2429 | |||
| 2430 | (defun compiler-macroexpand (form) | ||
| 2431 | (while | ||
| 2432 | (let ((func (car-safe form)) (handler nil)) | ||
| 2433 | (while (and (symbolp func) | ||
| 2434 | (not (setq handler (get func 'cl-compiler-macro))) | ||
| 2435 | (fboundp func) | ||
| 2436 | (or (not (eq (car-safe (symbol-function func)) 'autoload)) | ||
| 2437 | (load (nth 1 (symbol-function func))))) | ||
| 2438 | (setq func (symbol-function func))) | ||
| 2439 | (and handler | ||
| 2440 | (not (eq form (setq form (apply handler form (cdr form)))))))) | ||
| 2441 | form) | ||
| 2442 | |||
| 2443 | (defun cl-byte-compile-compiler-macro (form) | ||
| 2444 | (if (eq form (setq form (compiler-macroexpand form))) | ||
| 2445 | (byte-compile-normal-call form) | ||
| 2446 | (byte-compile-form form))) | ||
| 2447 | |||
| 2448 | (defmacro defsubst* (name args &rest body) | ||
| 2449 | "(defsubst* NAME ARGLIST [DOCSTRING] BODY...): define NAME as a function. | ||
| 2450 | Like `defun', except the function is automatically declared `inline', | ||
| 2451 | ARGLIST allows full Common Lisp conventions, and BODY is implicitly | ||
| 2452 | surrounded by (block NAME ...)." | ||
| 2453 | (let* ((argns (cl-arglist-args args)) (p argns) | ||
| 2454 | (pbody (cons 'progn body)) | ||
| 2455 | (unsafe (not (cl-safe-expr-p pbody)))) | ||
| 2456 | (while (and p (eq (cl-expr-contains args (car p)) 1)) (cl-pop p)) | ||
| 2457 | (list 'progn | ||
| 2458 | (if p nil ; give up if defaults refer to earlier args | ||
| 2459 | (list 'define-compiler-macro name | ||
| 2460 | (list* '&whole 'cl-whole '&cl-quote args) | ||
| 2461 | (list* 'cl-defsubst-expand (list 'quote argns) | ||
| 2462 | (list 'quote (list* 'block name body)) | ||
| 2463 | (not (or unsafe (cl-expr-access-order pbody argns))) | ||
| 2464 | (and (memq '&key args) 'cl-whole) unsafe argns))) | ||
| 2465 | (list* 'defun* name args body)))) | ||
| 2466 | |||
| 2467 | (defun cl-defsubst-expand (argns body simple whole unsafe &rest argvs) | ||
| 2468 | (if (and whole (not (cl-safe-expr-p (cons 'progn argvs)))) whole | ||
| 2469 | (if (cl-simple-exprs-p argvs) (setq simple t)) | ||
| 2470 | (let ((lets (delq nil | ||
| 2471 | (mapcar* (function | ||
| 2472 | (lambda (argn argv) | ||
| 2473 | (if (or simple (cl-const-expr-p argv)) | ||
| 2474 | (progn (setq body (subst argv argn body)) | ||
| 2475 | (and unsafe (list argn argv))) | ||
| 2476 | (list argn argv)))) | ||
| 2477 | argns argvs)))) | ||
| 2478 | (if lets (list 'let lets body) body)))) | ||
| 2479 | |||
| 2480 | |||
| 2481 | ;;; Compile-time optimizations for some functions defined in this package. | ||
| 2482 | ;;; Note that cl.el arranges to force cl-macs to be loaded at compile-time, | ||
| 2483 | ;;; mainly to make sure these macros will be present. | ||
| 2484 | |||
| 2485 | (put 'eql 'byte-compile nil) | ||
| 2486 | (define-compiler-macro eql (&whole form a b) | ||
| 2487 | (cond ((eq (cl-const-expr-p a) t) | ||
| 2488 | (let ((val (cl-const-expr-val a))) | ||
| 2489 | (if (and (numberp val) (not (integerp val))) | ||
| 2490 | (list 'equal a b) | ||
| 2491 | (list 'eq a b)))) | ||
| 2492 | ((eq (cl-const-expr-p b) t) | ||
| 2493 | (let ((val (cl-const-expr-val b))) | ||
| 2494 | (if (and (numberp val) (not (integerp val))) | ||
| 2495 | (list 'equal a b) | ||
| 2496 | (list 'eq a b)))) | ||
| 2497 | ((cl-simple-expr-p a 5) | ||
| 2498 | (list 'if (list 'numberp a) | ||
| 2499 | (list 'equal a b) | ||
| 2500 | (list 'eq a b))) | ||
| 2501 | ((and (cl-safe-expr-p a) | ||
| 2502 | (cl-simple-expr-p b 5)) | ||
| 2503 | (list 'if (list 'numberp b) | ||
| 2504 | (list 'equal a b) | ||
| 2505 | (list 'eq a b))) | ||
| 2506 | (t form))) | ||
| 2507 | |||
| 2508 | (define-compiler-macro member* (&whole form a list &rest keys) | ||
| 2509 | (let ((test (and (= (length keys) 2) (eq (car keys) ':test) | ||
| 2510 | (cl-const-expr-val (nth 1 keys))))) | ||
| 2511 | (cond ((eq test 'eq) (list 'memq a list)) | ||
| 2512 | ((eq test 'equal) (list 'member a list)) | ||
| 2513 | ((or (null keys) (eq test 'eql)) | ||
| 2514 | (if (eq (cl-const-expr-p a) t) | ||
| 2515 | (list (if (floatp-safe (cl-const-expr-val a)) 'member 'memq) | ||
| 2516 | a list) | ||
| 2517 | (if (eq (cl-const-expr-p list) t) | ||
| 2518 | (let ((p (cl-const-expr-val list)) (mb nil) (mq nil)) | ||
| 2519 | (if (not (cdr p)) | ||
| 2520 | (and p (list 'eql a (list 'quote (car p)))) | ||
| 2521 | (while p | ||
| 2522 | (if (floatp-safe (car p)) (setq mb t) | ||
| 2523 | (or (integerp (car p)) (symbolp (car p)) (setq mq t))) | ||
| 2524 | (setq p (cdr p))) | ||
| 2525 | (if (not mb) (list 'memq a list) | ||
| 2526 | (if (not mq) (list 'member a list) form)))) | ||
| 2527 | form))) | ||
| 2528 | (t form)))) | ||
| 2529 | |||
| 2530 | (define-compiler-macro assoc* (&whole form a list &rest keys) | ||
| 2531 | (let ((test (and (= (length keys) 2) (eq (car keys) ':test) | ||
| 2532 | (cl-const-expr-val (nth 1 keys))))) | ||
| 2533 | (cond ((eq test 'eq) (list 'assq a list)) | ||
| 2534 | ((eq test 'equal) (list 'assoc a list)) | ||
| 2535 | ((and (eq (cl-const-expr-p a) t) (or (null keys) (eq test 'eql))) | ||
| 2536 | (if (floatp-safe (cl-const-expr-val a)) | ||
| 2537 | (list 'assoc a list) (list 'assq a list))) | ||
| 2538 | (t form)))) | ||
| 2539 | |||
| 2540 | (define-compiler-macro adjoin (&whole form a list &rest keys) | ||
| 2541 | (if (and (cl-simple-expr-p a) (cl-simple-expr-p list) | ||
| 2542 | (not (memq ':key keys))) | ||
| 2543 | (list 'if (list* 'member* a list keys) list (list 'cons a list)) | ||
| 2544 | form)) | ||
| 2545 | |||
| 2546 | (define-compiler-macro list* (arg &rest others) | ||
| 2547 | (let* ((args (reverse (cons arg others))) | ||
| 2548 | (form (car args))) | ||
| 2549 | (while (setq args (cdr args)) | ||
| 2550 | (setq form (list 'cons (car args) form))) | ||
| 2551 | form)) | ||
| 2552 | |||
| 2553 | (define-compiler-macro get* (sym prop &optional def) | ||
| 2554 | (if def | ||
| 2555 | (list 'getf (list 'symbol-plist sym) prop def) | ||
| 2556 | (list 'get sym prop))) | ||
| 2557 | |||
| 2558 | (define-compiler-macro typep (&whole form val type) | ||
| 2559 | (if (cl-const-expr-p type) | ||
| 2560 | (let ((res (cl-make-type-test val (cl-const-expr-val type)))) | ||
| 2561 | (if (or (memq (cl-expr-contains res val) '(nil 1)) | ||
| 2562 | (cl-simple-expr-p val)) res | ||
| 2563 | (let ((temp (gensym))) | ||
| 2564 | (list 'let (list (list temp val)) (subst temp val res))))) | ||
| 2565 | form)) | ||
| 2566 | |||
| 2567 | |||
| 2568 | (mapcar (function | ||
| 2569 | (lambda (y) | ||
| 2570 | (put (car y) 'side-effect-free t) | ||
| 2571 | (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) | ||
| 2572 | (put (car y) 'cl-compiler-macro | ||
| 2573 | (list 'lambda '(w x) | ||
| 2574 | (if (symbolp (cadr y)) | ||
| 2575 | (list 'list (list 'quote (cadr y)) | ||
| 2576 | (list 'list (list 'quote (caddr y)) 'x)) | ||
| 2577 | (cons 'list (cdr y))))))) | ||
| 2578 | '((first 'car x) (second 'cadr x) (third 'caddr x) (fourth 'cadddr x) | ||
| 2579 | (fifth 'nth 4 x) (sixth 'nth 5 x) (seventh 'nth 6 x) | ||
| 2580 | (eighth 'nth 7 x) (ninth 'nth 8 x) (tenth 'nth 9 x) | ||
| 2581 | (rest 'cdr x) (endp 'null x) (plusp '> x 0) (minusp '< x 0) | ||
| 2582 | (caar car car) (cadr car cdr) (cdar cdr car) (cddr cdr cdr) | ||
| 2583 | (caaar car caar) (caadr car cadr) (cadar car cdar) | ||
| 2584 | (caddr car cddr) (cdaar cdr caar) (cdadr cdr cadr) | ||
| 2585 | (cddar cdr cdar) (cdddr cdr cddr) (caaaar car caaar) | ||
| 2586 | (caaadr car caadr) (caadar car cadar) (caaddr car caddr) | ||
| 2587 | (cadaar car cdaar) (cadadr car cdadr) (caddar car cddar) | ||
| 2588 | (cadddr car cdddr) (cdaaar cdr caaar) (cdaadr cdr caadr) | ||
| 2589 | (cdadar cdr cadar) (cdaddr cdr caddr) (cddaar cdr cdaar) | ||
| 2590 | (cddadr cdr cdadr) (cdddar cdr cddar) (cddddr cdr cdddr) )) | ||
| 2591 | |||
| 2592 | ;;; Things that are inline. | ||
| 2593 | (proclaim '(inline floatp-safe acons map concatenate notany notevery | ||
| 2594 | cl-set-elt revappend nreconc gethash)) | ||
| 2595 | |||
| 2596 | ;;; Things that are side-effect-free. | ||
| 2597 | (mapcar (function (lambda (x) (put x 'side-effect-free t))) | ||
| 2598 | '(oddp evenp abs expt signum last butlast ldiff pairlis gcd lcm | ||
| 2599 | isqrt floor* ceiling* truncate* round* mod* rem* subseq | ||
| 2600 | list-length get* getf gethash hash-table-count)) | ||
| 2601 | |||
| 2602 | ;;; Things that are side-effect-and-error-free. | ||
| 2603 | (mapcar (function (lambda (x) (put x 'side-effect-free 'error-free))) | ||
| 2604 | '(eql floatp-safe list* subst acons equalp random-state-p | ||
| 2605 | copy-tree sublis hash-table-p)) | ||
| 2606 | |||
| 2607 | |||
| 2608 | (run-hooks 'cl-macs-load-hook) | ||
| 2609 | |||
| 2610 | ;;; cl-macs.el ends here | ||
diff --git a/lisp/emacs-lisp/cl-seq.el b/lisp/emacs-lisp/cl-seq.el new file mode 100644 index 00000000000..b48d73e157f --- /dev/null +++ b/lisp/emacs-lisp/cl-seq.el | |||
| @@ -0,0 +1,920 @@ | |||
| 1 | ;; cl-seq.el --- Common Lisp extensions for GNU Emacs Lisp (part three) | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Dave Gillespie <daveg@synaptics.com> | ||
| 6 | ;; Version: 2.02 | ||
| 7 | ;; Keywords: extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 14 | ;; any later version. | ||
| 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 | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | ;; Commentary: | ||
| 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 | ;; | ||
| 34 | ;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. | ||
| 35 | ;; | ||
| 36 | ;; Bug reports, comments, and suggestions are welcome! | ||
| 37 | |||
| 38 | ;; This file contains the Common Lisp sequence and list functions | ||
| 39 | ;; which take keyword arguments. | ||
| 40 | |||
| 41 | ;; See cl.el for Change Log. | ||
| 42 | |||
| 43 | |||
| 44 | ;; Code: | ||
| 45 | |||
| 46 | (or (memq 'cl-19 features) | ||
| 47 | (error "Tried to load `cl-seq' before `cl'!")) | ||
| 48 | |||
| 49 | |||
| 50 | ;;; We define these here so that this file can compile without having | ||
| 51 | ;;; loaded the cl.el file already. | ||
| 52 | |||
| 53 | (defmacro cl-push (x place) (list 'setq place (list 'cons x place))) | ||
| 54 | (defmacro cl-pop (place) | ||
| 55 | (list 'car (list 'prog1 place (list 'setq place (list 'cdr place))))) | ||
| 56 | |||
| 57 | |||
| 58 | ;;; Keyword parsing. This is special-cased here so that we can compile | ||
| 59 | ;;; this file independent from cl-macs. | ||
| 60 | |||
| 61 | (defmacro cl-parsing-keywords (kwords other-keys &rest body) | ||
| 62 | (cons | ||
| 63 | 'let* | ||
| 64 | (cons (mapcar | ||
| 65 | (function | ||
| 66 | (lambda (x) | ||
| 67 | (let* ((var (if (consp x) (car x) x)) | ||
| 68 | (mem (list 'car (list 'cdr (list 'memq (list 'quote var) | ||
| 69 | 'cl-keys))))) | ||
| 70 | (if (eq var ':test-not) | ||
| 71 | (setq mem (list 'and mem (list 'setq 'cl-test mem) t))) | ||
| 72 | (if (eq var ':if-not) | ||
| 73 | (setq mem (list 'and mem (list 'setq 'cl-if mem) t))) | ||
| 74 | (list (intern | ||
| 75 | (format "cl-%s" (substring (symbol-name var) 1))) | ||
| 76 | (if (consp x) (list 'or mem (car (cdr x))) mem))))) | ||
| 77 | kwords) | ||
| 78 | (append | ||
| 79 | (and (not (eq other-keys t)) | ||
| 80 | (list | ||
| 81 | (list 'let '((cl-keys-temp cl-keys)) | ||
| 82 | (list 'while 'cl-keys-temp | ||
| 83 | (list 'or (list 'memq '(car cl-keys-temp) | ||
| 84 | (list 'quote | ||
| 85 | (mapcar | ||
| 86 | (function | ||
| 87 | (lambda (x) | ||
| 88 | (if (consp x) | ||
| 89 | (car x) x))) | ||
| 90 | (append kwords | ||
| 91 | other-keys)))) | ||
| 92 | '(car (cdr (memq (quote :allow-other-keys) | ||
| 93 | cl-keys))) | ||
| 94 | '(error "Bad keyword argument %s" | ||
| 95 | (car cl-keys-temp))) | ||
| 96 | '(setq cl-keys-temp (cdr (cdr cl-keys-temp))))))) | ||
| 97 | body)))) | ||
| 98 | (put 'cl-parsing-keywords 'lisp-indent-function 2) | ||
| 99 | (put 'cl-parsing-keywords 'edebug-form-spec '(sexp sexp &rest form)) | ||
| 100 | |||
| 101 | (defmacro cl-check-key (x) | ||
| 102 | (list 'if 'cl-key (list 'funcall 'cl-key x) x)) | ||
| 103 | |||
| 104 | (defmacro cl-check-test-nokey (item x) | ||
| 105 | (list 'cond | ||
| 106 | (list 'cl-test | ||
| 107 | (list 'eq (list 'not (list 'funcall 'cl-test item x)) | ||
| 108 | 'cl-test-not)) | ||
| 109 | (list 'cl-if | ||
| 110 | (list 'eq (list 'not (list 'funcall 'cl-if x)) 'cl-if-not)) | ||
| 111 | (list 't (list 'if (list 'numberp item) | ||
| 112 | (list 'equal item x) (list 'eq item x))))) | ||
| 113 | |||
| 114 | (defmacro cl-check-test (item x) | ||
| 115 | (list 'cl-check-test-nokey item (list 'cl-check-key x))) | ||
| 116 | |||
| 117 | (defmacro cl-check-match (x y) | ||
| 118 | (setq x (list 'cl-check-key x) y (list 'cl-check-key y)) | ||
| 119 | (list 'if 'cl-test | ||
| 120 | (list 'eq (list 'not (list 'funcall 'cl-test x y)) 'cl-test-not) | ||
| 121 | (list 'if (list 'numberp x) | ||
| 122 | (list 'equal x y) (list 'eq x y)))) | ||
| 123 | |||
| 124 | (put 'cl-check-key 'edebug-form-spec 'edebug-forms) | ||
| 125 | (put 'cl-check-test 'edebug-form-spec 'edebug-forms) | ||
| 126 | (put 'cl-check-test-nokey 'edebug-form-spec 'edebug-forms) | ||
| 127 | (put 'cl-check-match 'edebug-form-spec 'edebug-forms) | ||
| 128 | |||
| 129 | (defvar cl-test) (defvar cl-test-not) | ||
| 130 | (defvar cl-if) (defvar cl-if-not) | ||
| 131 | (defvar cl-key) | ||
| 132 | |||
| 133 | |||
| 134 | (defun reduce (cl-func cl-seq &rest cl-keys) | ||
| 135 | "Reduce two-argument FUNCTION across SEQUENCE. | ||
| 136 | Keywords supported: :start :end :from-end :initial-value :key" | ||
| 137 | (cl-parsing-keywords (:from-end (:start 0) :end :initial-value :key) () | ||
| 138 | (or (listp cl-seq) (setq cl-seq (append cl-seq nil))) | ||
| 139 | (setq cl-seq (subseq cl-seq cl-start cl-end)) | ||
| 140 | (if cl-from-end (setq cl-seq (nreverse cl-seq))) | ||
| 141 | (let ((cl-accum (cond ((memq ':initial-value cl-keys) cl-initial-value) | ||
| 142 | (cl-seq (cl-check-key (cl-pop cl-seq))) | ||
| 143 | (t (funcall cl-func))))) | ||
| 144 | (if cl-from-end | ||
| 145 | (while cl-seq | ||
| 146 | (setq cl-accum (funcall cl-func (cl-check-key (cl-pop cl-seq)) | ||
| 147 | cl-accum))) | ||
| 148 | (while cl-seq | ||
| 149 | (setq cl-accum (funcall cl-func cl-accum | ||
| 150 | (cl-check-key (cl-pop cl-seq)))))) | ||
| 151 | cl-accum))) | ||
| 152 | |||
| 153 | (defun fill (seq item &rest cl-keys) | ||
| 154 | "Fill the elements of SEQ with ITEM. | ||
| 155 | Keywords supported: :start :end" | ||
| 156 | (cl-parsing-keywords ((:start 0) :end) () | ||
| 157 | (if (listp seq) | ||
| 158 | (let ((p (nthcdr cl-start seq)) | ||
| 159 | (n (if cl-end (- cl-end cl-start) 8000000))) | ||
| 160 | (while (and p (>= (setq n (1- n)) 0)) | ||
| 161 | (setcar p item) | ||
| 162 | (setq p (cdr p)))) | ||
| 163 | (or cl-end (setq cl-end (length seq))) | ||
| 164 | (if (and (= cl-start 0) (= cl-end (length seq))) | ||
| 165 | (fillarray seq item) | ||
| 166 | (while (< cl-start cl-end) | ||
| 167 | (aset seq cl-start item) | ||
| 168 | (setq cl-start (1+ cl-start))))) | ||
| 169 | seq)) | ||
| 170 | |||
| 171 | (defun replace (cl-seq1 cl-seq2 &rest cl-keys) | ||
| 172 | "Replace the elements of SEQ1 with the elements of SEQ2. | ||
| 173 | SEQ1 is destructively modified, then returned. | ||
| 174 | Keywords supported: :start1 :end1 :start2 :end2" | ||
| 175 | (cl-parsing-keywords ((:start1 0) :end1 (:start2 0) :end2) () | ||
| 176 | (if (and (eq cl-seq1 cl-seq2) (<= cl-start2 cl-start1)) | ||
| 177 | (or (= cl-start1 cl-start2) | ||
| 178 | (let* ((cl-len (length cl-seq1)) | ||
| 179 | (cl-n (min (- (or cl-end1 cl-len) cl-start1) | ||
| 180 | (- (or cl-end2 cl-len) cl-start2)))) | ||
| 181 | (while (>= (setq cl-n (1- cl-n)) 0) | ||
| 182 | (cl-set-elt cl-seq1 (+ cl-start1 cl-n) | ||
| 183 | (elt cl-seq2 (+ cl-start2 cl-n)))))) | ||
| 184 | (if (listp cl-seq1) | ||
| 185 | (let ((cl-p1 (nthcdr cl-start1 cl-seq1)) | ||
| 186 | (cl-n1 (if cl-end1 (- cl-end1 cl-start1) 4000000))) | ||
| 187 | (if (listp cl-seq2) | ||
| 188 | (let ((cl-p2 (nthcdr cl-start2 cl-seq2)) | ||
| 189 | (cl-n (min cl-n1 | ||
| 190 | (if cl-end2 (- cl-end2 cl-start2) 4000000)))) | ||
| 191 | (while (and cl-p1 cl-p2 (>= (setq cl-n (1- cl-n)) 0)) | ||
| 192 | (setcar cl-p1 (car cl-p2)) | ||
| 193 | (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2)))) | ||
| 194 | (setq cl-end2 (min (or cl-end2 (length cl-seq2)) | ||
| 195 | (+ cl-start2 cl-n1))) | ||
| 196 | (while (and cl-p1 (< cl-start2 cl-end2)) | ||
| 197 | (setcar cl-p1 (aref cl-seq2 cl-start2)) | ||
| 198 | (setq cl-p1 (cdr cl-p1) cl-start2 (1+ cl-start2))))) | ||
| 199 | (setq cl-end1 (min (or cl-end1 (length cl-seq1)) | ||
| 200 | (+ cl-start1 (- (or cl-end2 (length cl-seq2)) | ||
| 201 | cl-start2)))) | ||
| 202 | (if (listp cl-seq2) | ||
| 203 | (let ((cl-p2 (nthcdr cl-start2 cl-seq2))) | ||
| 204 | (while (< cl-start1 cl-end1) | ||
| 205 | (aset cl-seq1 cl-start1 (car cl-p2)) | ||
| 206 | (setq cl-p2 (cdr cl-p2) cl-start1 (1+ cl-start1)))) | ||
| 207 | (while (< cl-start1 cl-end1) | ||
| 208 | (aset cl-seq1 cl-start1 (aref cl-seq2 cl-start2)) | ||
| 209 | (setq cl-start2 (1+ cl-start2) cl-start1 (1+ cl-start1)))))) | ||
| 210 | cl-seq1)) | ||
| 211 | |||
| 212 | (defun remove* (cl-item cl-seq &rest cl-keys) | ||
| 213 | "Remove all occurrences of ITEM in SEQ. | ||
| 214 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 215 | to avoid corrupting the original SEQ. | ||
| 216 | Keywords supported: :test :test-not :key :count :start :end :from-end" | ||
| 217 | (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end | ||
| 218 | (:start 0) :end) () | ||
| 219 | (if (<= (or cl-count (setq cl-count 8000000)) 0) | ||
| 220 | cl-seq | ||
| 221 | (if (or (nlistp cl-seq) (and cl-from-end (< cl-count 4000000))) | ||
| 222 | (let ((cl-i (cl-position cl-item cl-seq cl-start cl-end | ||
| 223 | cl-from-end))) | ||
| 224 | (if cl-i | ||
| 225 | (let ((cl-res (apply 'delete* cl-item (append cl-seq nil) | ||
| 226 | (append (if cl-from-end | ||
| 227 | (list ':end (1+ cl-i)) | ||
| 228 | (list ':start cl-i)) | ||
| 229 | cl-keys)))) | ||
| 230 | (if (listp cl-seq) cl-res | ||
| 231 | (if (stringp cl-seq) (concat cl-res) (vconcat cl-res)))) | ||
| 232 | cl-seq)) | ||
| 233 | (setq cl-end (- (or cl-end 8000000) cl-start)) | ||
| 234 | (if (= cl-start 0) | ||
| 235 | (while (and cl-seq (> cl-end 0) | ||
| 236 | (cl-check-test cl-item (car cl-seq)) | ||
| 237 | (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) | ||
| 238 | (> (setq cl-count (1- cl-count)) 0)))) | ||
| 239 | (if (and (> cl-count 0) (> cl-end 0)) | ||
| 240 | (let ((cl-p (if (> cl-start 0) (nthcdr cl-start cl-seq) | ||
| 241 | (setq cl-end (1- cl-end)) (cdr cl-seq)))) | ||
| 242 | (while (and cl-p (> cl-end 0) | ||
| 243 | (not (cl-check-test cl-item (car cl-p)))) | ||
| 244 | (setq cl-p (cdr cl-p) cl-end (1- cl-end))) | ||
| 245 | (if (and cl-p (> cl-end 0)) | ||
| 246 | (nconc (ldiff cl-seq cl-p) | ||
| 247 | (if (= cl-count 1) (cdr cl-p) | ||
| 248 | (and (cdr cl-p) | ||
| 249 | (apply 'delete* cl-item | ||
| 250 | (copy-sequence (cdr cl-p)) | ||
| 251 | ':start 0 ':end (1- cl-end) | ||
| 252 | ':count (1- cl-count) cl-keys)))) | ||
| 253 | cl-seq)) | ||
| 254 | cl-seq))))) | ||
| 255 | |||
| 256 | (defun remove-if (cl-pred cl-list &rest cl-keys) | ||
| 257 | "Remove all items satisfying PREDICATE in SEQ. | ||
| 258 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 259 | to avoid corrupting the original SEQ. | ||
| 260 | Keywords supported: :key :count :start :end :from-end" | ||
| 261 | (apply 'remove* nil cl-list ':if cl-pred cl-keys)) | ||
| 262 | |||
| 263 | (defun remove-if-not (cl-pred cl-list &rest cl-keys) | ||
| 264 | "Remove all items not satisfying PREDICATE in SEQ. | ||
| 265 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 266 | to avoid corrupting the original SEQ. | ||
| 267 | Keywords supported: :key :count :start :end :from-end" | ||
| 268 | (apply 'remove* nil cl-list ':if-not cl-pred cl-keys)) | ||
| 269 | |||
| 270 | (defun delete* (cl-item cl-seq &rest cl-keys) | ||
| 271 | "Remove all occurrences of ITEM in SEQ. | ||
| 272 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 273 | Keywords supported: :test :test-not :key :count :start :end :from-end" | ||
| 274 | (cl-parsing-keywords (:test :test-not :key :if :if-not :count :from-end | ||
| 275 | (:start 0) :end) () | ||
| 276 | (if (<= (or cl-count (setq cl-count 8000000)) 0) | ||
| 277 | cl-seq | ||
| 278 | (if (listp cl-seq) | ||
| 279 | (if (and cl-from-end (< cl-count 4000000)) | ||
| 280 | (let (cl-i) | ||
| 281 | (while (and (>= (setq cl-count (1- cl-count)) 0) | ||
| 282 | (setq cl-i (cl-position cl-item cl-seq cl-start | ||
| 283 | cl-end cl-from-end))) | ||
| 284 | (if (= cl-i 0) (setq cl-seq (cdr cl-seq)) | ||
| 285 | (let ((cl-tail (nthcdr (1- cl-i) cl-seq))) | ||
| 286 | (setcdr cl-tail (cdr (cdr cl-tail))))) | ||
| 287 | (setq cl-end cl-i)) | ||
| 288 | cl-seq) | ||
| 289 | (setq cl-end (- (or cl-end 8000000) cl-start)) | ||
| 290 | (if (= cl-start 0) | ||
| 291 | (progn | ||
| 292 | (while (and cl-seq | ||
| 293 | (> cl-end 0) | ||
| 294 | (cl-check-test cl-item (car cl-seq)) | ||
| 295 | (setq cl-end (1- cl-end) cl-seq (cdr cl-seq)) | ||
| 296 | (> (setq cl-count (1- cl-count)) 0))) | ||
| 297 | (setq cl-end (1- cl-end))) | ||
| 298 | (setq cl-start (1- cl-start))) | ||
| 299 | (if (and (> cl-count 0) (> cl-end 0)) | ||
| 300 | (let ((cl-p (nthcdr cl-start cl-seq))) | ||
| 301 | (while (and (cdr cl-p) (> cl-end 0)) | ||
| 302 | (if (cl-check-test cl-item (car (cdr cl-p))) | ||
| 303 | (progn | ||
| 304 | (setcdr cl-p (cdr (cdr cl-p))) | ||
| 305 | (if (= (setq cl-count (1- cl-count)) 0) | ||
| 306 | (setq cl-end 1))) | ||
| 307 | (setq cl-p (cdr cl-p))) | ||
| 308 | (setq cl-end (1- cl-end))))) | ||
| 309 | cl-seq) | ||
| 310 | (apply 'remove* cl-item cl-seq cl-keys))))) | ||
| 311 | |||
| 312 | (defun delete-if (cl-pred cl-list &rest cl-keys) | ||
| 313 | "Remove all items satisfying PREDICATE in SEQ. | ||
| 314 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 315 | Keywords supported: :key :count :start :end :from-end" | ||
| 316 | (apply 'delete* nil cl-list ':if cl-pred cl-keys)) | ||
| 317 | |||
| 318 | (defun delete-if-not (cl-pred cl-list &rest cl-keys) | ||
| 319 | "Remove all items not satisfying PREDICATE in SEQ. | ||
| 320 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 321 | Keywords supported: :key :count :start :end :from-end" | ||
| 322 | (apply 'delete* nil cl-list ':if-not cl-pred cl-keys)) | ||
| 323 | |||
| 324 | (or (and (fboundp 'delete) (subrp (symbol-function 'delete))) | ||
| 325 | (defalias 'delete (function (lambda (x y) (delete* x y ':test 'equal))))) | ||
| 326 | (defun remove (x y) (remove* x y ':test 'equal)) | ||
| 327 | (defun remq (x y) (if (memq x y) (delq x (copy-list y)) y)) | ||
| 328 | |||
| 329 | (defun remove-duplicates (cl-seq &rest cl-keys) | ||
| 330 | "Return a copy of SEQ with all duplicate elements removed. | ||
| 331 | Keywords supported: :test :test-not :key :start :end :from-end" | ||
| 332 | (cl-delete-duplicates cl-seq cl-keys t)) | ||
| 333 | |||
| 334 | (defun delete-duplicates (cl-seq &rest cl-keys) | ||
| 335 | "Remove all duplicate elements from SEQ (destructively). | ||
| 336 | Keywords supported: :test :test-not :key :start :end :from-end" | ||
| 337 | (cl-delete-duplicates cl-seq cl-keys nil)) | ||
| 338 | |||
| 339 | (defun cl-delete-duplicates (cl-seq cl-keys cl-copy) | ||
| 340 | (if (listp cl-seq) | ||
| 341 | (cl-parsing-keywords (:test :test-not :key (:start 0) :end :from-end :if) | ||
| 342 | () | ||
| 343 | (if cl-from-end | ||
| 344 | (let ((cl-p (nthcdr cl-start cl-seq)) cl-i) | ||
| 345 | (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) | ||
| 346 | (while (> cl-end 1) | ||
| 347 | (setq cl-i 0) | ||
| 348 | (while (setq cl-i (cl-position (cl-check-key (car cl-p)) | ||
| 349 | (cdr cl-p) cl-i (1- cl-end))) | ||
| 350 | (if cl-copy (setq cl-seq (copy-sequence cl-seq) | ||
| 351 | cl-p (nthcdr cl-start cl-seq) cl-copy nil)) | ||
| 352 | (let ((cl-tail (nthcdr cl-i cl-p))) | ||
| 353 | (setcdr cl-tail (cdr (cdr cl-tail)))) | ||
| 354 | (setq cl-end (1- cl-end))) | ||
| 355 | (setq cl-p (cdr cl-p) cl-end (1- cl-end) | ||
| 356 | cl-start (1+ cl-start))) | ||
| 357 | cl-seq) | ||
| 358 | (setq cl-end (- (or cl-end (length cl-seq)) cl-start)) | ||
| 359 | (while (and (cdr cl-seq) (= cl-start 0) (> cl-end 1) | ||
| 360 | (cl-position (cl-check-key (car cl-seq)) | ||
| 361 | (cdr cl-seq) 0 (1- cl-end))) | ||
| 362 | (setq cl-seq (cdr cl-seq) cl-end (1- cl-end))) | ||
| 363 | (let ((cl-p (if (> cl-start 0) (nthcdr (1- cl-start) cl-seq) | ||
| 364 | (setq cl-end (1- cl-end) cl-start 1) cl-seq))) | ||
| 365 | (while (and (cdr (cdr cl-p)) (> cl-end 1)) | ||
| 366 | (if (cl-position (cl-check-key (car (cdr cl-p))) | ||
| 367 | (cdr (cdr cl-p)) 0 (1- cl-end)) | ||
| 368 | (progn | ||
| 369 | (if cl-copy (setq cl-seq (copy-sequence cl-seq) | ||
| 370 | cl-p (nthcdr (1- cl-start) cl-seq) | ||
| 371 | cl-copy nil)) | ||
| 372 | (setcdr cl-p (cdr (cdr cl-p)))) | ||
| 373 | (setq cl-p (cdr cl-p))) | ||
| 374 | (setq cl-end (1- cl-end) cl-start (1+ cl-start))) | ||
| 375 | cl-seq))) | ||
| 376 | (let ((cl-res (cl-delete-duplicates (append cl-seq nil) cl-keys nil))) | ||
| 377 | (if (stringp cl-seq) (concat cl-res) (vconcat cl-res))))) | ||
| 378 | |||
| 379 | (defun substitute (cl-new cl-old cl-seq &rest cl-keys) | ||
| 380 | "Substitute NEW for OLD in SEQ. | ||
| 381 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 382 | to avoid corrupting the original SEQ. | ||
| 383 | Keywords supported: :test :test-not :key :count :start :end :from-end" | ||
| 384 | (cl-parsing-keywords (:test :test-not :key :if :if-not :count | ||
| 385 | (:start 0) :end :from-end) () | ||
| 386 | (if (or (eq cl-old cl-new) | ||
| 387 | (<= (or cl-count (setq cl-from-end nil cl-count 8000000)) 0)) | ||
| 388 | cl-seq | ||
| 389 | (let ((cl-i (cl-position cl-old cl-seq cl-start cl-end))) | ||
| 390 | (if (not cl-i) | ||
| 391 | cl-seq | ||
| 392 | (setq cl-seq (copy-sequence cl-seq)) | ||
| 393 | (or cl-from-end | ||
| 394 | (progn (cl-set-elt cl-seq cl-i cl-new) | ||
| 395 | (setq cl-i (1+ cl-i) cl-count (1- cl-count)))) | ||
| 396 | (apply 'nsubstitute cl-new cl-old cl-seq ':count cl-count | ||
| 397 | ':start cl-i cl-keys)))))) | ||
| 398 | |||
| 399 | (defun substitute-if (cl-new cl-pred cl-list &rest cl-keys) | ||
| 400 | "Substitute NEW for all items satisfying PREDICATE in SEQ. | ||
| 401 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 402 | to avoid corrupting the original SEQ. | ||
| 403 | Keywords supported: :key :count :start :end :from-end" | ||
| 404 | (apply 'substitute cl-new nil cl-list ':if cl-pred cl-keys)) | ||
| 405 | |||
| 406 | (defun substitute-if-not (cl-new cl-pred cl-list &rest cl-keys) | ||
| 407 | "Substitute NEW for all items not satisfying PREDICATE in SEQ. | ||
| 408 | This is a non-destructive function; it makes a copy of SEQ if necessary | ||
| 409 | to avoid corrupting the original SEQ. | ||
| 410 | Keywords supported: :key :count :start :end :from-end" | ||
| 411 | (apply 'substitute cl-new nil cl-list ':if-not cl-pred cl-keys)) | ||
| 412 | |||
| 413 | (defun nsubstitute (cl-new cl-old cl-seq &rest cl-keys) | ||
| 414 | "Substitute NEW for OLD in SEQ. | ||
| 415 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 416 | Keywords supported: :test :test-not :key :count :start :end :from-end" | ||
| 417 | (cl-parsing-keywords (:test :test-not :key :if :if-not :count | ||
| 418 | (:start 0) :end :from-end) () | ||
| 419 | (or (eq cl-old cl-new) (<= (or cl-count (setq cl-count 8000000)) 0) | ||
| 420 | (if (and (listp cl-seq) (or (not cl-from-end) (> cl-count 4000000))) | ||
| 421 | (let ((cl-p (nthcdr cl-start cl-seq))) | ||
| 422 | (setq cl-end (- (or cl-end 8000000) cl-start)) | ||
| 423 | (while (and cl-p (> cl-end 0) (> cl-count 0)) | ||
| 424 | (if (cl-check-test cl-old (car cl-p)) | ||
| 425 | (progn | ||
| 426 | (setcar cl-p cl-new) | ||
| 427 | (setq cl-count (1- cl-count)))) | ||
| 428 | (setq cl-p (cdr cl-p) cl-end (1- cl-end)))) | ||
| 429 | (or cl-end (setq cl-end (length cl-seq))) | ||
| 430 | (if cl-from-end | ||
| 431 | (while (and (< cl-start cl-end) (> cl-count 0)) | ||
| 432 | (setq cl-end (1- cl-end)) | ||
| 433 | (if (cl-check-test cl-old (elt cl-seq cl-end)) | ||
| 434 | (progn | ||
| 435 | (cl-set-elt cl-seq cl-end cl-new) | ||
| 436 | (setq cl-count (1- cl-count))))) | ||
| 437 | (while (and (< cl-start cl-end) (> cl-count 0)) | ||
| 438 | (if (cl-check-test cl-old (aref cl-seq cl-start)) | ||
| 439 | (progn | ||
| 440 | (aset cl-seq cl-start cl-new) | ||
| 441 | (setq cl-count (1- cl-count)))) | ||
| 442 | (setq cl-start (1+ cl-start)))))) | ||
| 443 | cl-seq)) | ||
| 444 | |||
| 445 | (defun nsubstitute-if (cl-new cl-pred cl-list &rest cl-keys) | ||
| 446 | "Substitute NEW for all items satisfying PREDICATE in SEQ. | ||
| 447 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 448 | Keywords supported: :key :count :start :end :from-end" | ||
| 449 | (apply 'nsubstitute cl-new nil cl-list ':if cl-pred cl-keys)) | ||
| 450 | |||
| 451 | (defun nsubstitute-if-not (cl-new cl-pred cl-list &rest cl-keys) | ||
| 452 | "Substitute NEW for all items not satisfying PREDICATE in SEQ. | ||
| 453 | This is a destructive function; it reuses the storage of SEQ whenever possible. | ||
| 454 | Keywords supported: :key :count :start :end :from-end" | ||
| 455 | (apply 'nsubstitute cl-new nil cl-list ':if-not cl-pred cl-keys)) | ||
| 456 | |||
| 457 | (defun find (cl-item cl-seq &rest cl-keys) | ||
| 458 | "Find the first occurrence of ITEM in LIST. | ||
| 459 | Return the matching ITEM, or nil if not found. | ||
| 460 | Keywords supported: :test :test-not :key :start :end :from-end" | ||
| 461 | (let ((cl-pos (apply 'position cl-item cl-seq cl-keys))) | ||
| 462 | (and cl-pos (elt cl-seq cl-pos)))) | ||
| 463 | |||
| 464 | (defun find-if (cl-pred cl-list &rest cl-keys) | ||
| 465 | "Find the first item satisfying PREDICATE in LIST. | ||
| 466 | Return the matching ITEM, or nil if not found. | ||
| 467 | Keywords supported: :key :start :end :from-end" | ||
| 468 | (apply 'find nil cl-list ':if cl-pred cl-keys)) | ||
| 469 | |||
| 470 | (defun find-if-not (cl-pred cl-list &rest cl-keys) | ||
| 471 | "Find the first item not satisfying PREDICATE in LIST. | ||
| 472 | Return the matching ITEM, or nil if not found. | ||
| 473 | Keywords supported: :key :start :end :from-end" | ||
| 474 | (apply 'find nil cl-list ':if-not cl-pred cl-keys)) | ||
| 475 | |||
| 476 | (defun position (cl-item cl-seq &rest cl-keys) | ||
| 477 | "Find the first occurrence of ITEM in LIST. | ||
| 478 | Return the index of the matching item, or nil if not found. | ||
| 479 | Keywords supported: :test :test-not :key :start :end :from-end" | ||
| 480 | (cl-parsing-keywords (:test :test-not :key :if :if-not | ||
| 481 | (:start 0) :end :from-end) () | ||
| 482 | (cl-position cl-item cl-seq cl-start cl-end cl-from-end))) | ||
| 483 | |||
| 484 | (defun cl-position (cl-item cl-seq cl-start &optional cl-end cl-from-end) | ||
| 485 | (if (listp cl-seq) | ||
| 486 | (let ((cl-p (nthcdr cl-start cl-seq))) | ||
| 487 | (or cl-end (setq cl-end 8000000)) | ||
| 488 | (let ((cl-res nil)) | ||
| 489 | (while (and cl-p (< cl-start cl-end) (or (not cl-res) cl-from-end)) | ||
| 490 | (if (cl-check-test cl-item (car cl-p)) | ||
| 491 | (setq cl-res cl-start)) | ||
| 492 | (setq cl-p (cdr cl-p) cl-start (1+ cl-start))) | ||
| 493 | cl-res)) | ||
| 494 | (or cl-end (setq cl-end (length cl-seq))) | ||
| 495 | (if cl-from-end | ||
| 496 | (progn | ||
| 497 | (while (and (>= (setq cl-end (1- cl-end)) cl-start) | ||
| 498 | (not (cl-check-test cl-item (aref cl-seq cl-end))))) | ||
| 499 | (and (>= cl-end cl-start) cl-end)) | ||
| 500 | (while (and (< cl-start cl-end) | ||
| 501 | (not (cl-check-test cl-item (aref cl-seq cl-start)))) | ||
| 502 | (setq cl-start (1+ cl-start))) | ||
| 503 | (and (< cl-start cl-end) cl-start)))) | ||
| 504 | |||
| 505 | (defun position-if (cl-pred cl-list &rest cl-keys) | ||
| 506 | "Find the first item satisfying PREDICATE in LIST. | ||
| 507 | Return the index of the matching item, or nil if not found. | ||
| 508 | Keywords supported: :key :start :end :from-end" | ||
| 509 | (apply 'position nil cl-list ':if cl-pred cl-keys)) | ||
| 510 | |||
| 511 | (defun position-if-not (cl-pred cl-list &rest cl-keys) | ||
| 512 | "Find the first item not satisfying PREDICATE in LIST. | ||
| 513 | Return the index of the matching item, or nil if not found. | ||
| 514 | Keywords supported: :key :start :end :from-end" | ||
| 515 | (apply 'position nil cl-list ':if-not cl-pred cl-keys)) | ||
| 516 | |||
| 517 | (defun count (cl-item cl-seq &rest cl-keys) | ||
| 518 | "Count the number of occurrences of ITEM in LIST. | ||
| 519 | Keywords supported: :test :test-not :key :start :end" | ||
| 520 | (cl-parsing-keywords (:test :test-not :key :if :if-not (:start 0) :end) () | ||
| 521 | (let ((cl-count 0) cl-x) | ||
| 522 | (or cl-end (setq cl-end (length cl-seq))) | ||
| 523 | (if (consp cl-seq) (setq cl-seq (nthcdr cl-start cl-seq))) | ||
| 524 | (while (< cl-start cl-end) | ||
| 525 | (setq cl-x (if (consp cl-seq) (cl-pop cl-seq) (aref cl-seq cl-start))) | ||
| 526 | (if (cl-check-test cl-item cl-x) (setq cl-count (1+ cl-count))) | ||
| 527 | (setq cl-start (1+ cl-start))) | ||
| 528 | cl-count))) | ||
| 529 | |||
| 530 | (defun count-if (cl-pred cl-list &rest cl-keys) | ||
| 531 | "Count the number of items satisfying PREDICATE in LIST. | ||
| 532 | Keywords supported: :key :start :end" | ||
| 533 | (apply 'count nil cl-list ':if cl-pred cl-keys)) | ||
| 534 | |||
| 535 | (defun count-if-not (cl-pred cl-list &rest cl-keys) | ||
| 536 | "Count the number of items not satisfying PREDICATE in LIST. | ||
| 537 | Keywords supported: :key :start :end" | ||
| 538 | (apply 'count nil cl-list ':if-not cl-pred cl-keys)) | ||
| 539 | |||
| 540 | (defun mismatch (cl-seq1 cl-seq2 &rest cl-keys) | ||
| 541 | "Compare SEQ1 with SEQ2, return index of first mismatching element. | ||
| 542 | Return nil if the sequences match. If one sequence is a prefix of the | ||
| 543 | other, the return value indicates the end of the shorted sequence. | ||
| 544 | Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" | ||
| 545 | (cl-parsing-keywords (:test :test-not :key :from-end | ||
| 546 | (:start1 0) :end1 (:start2 0) :end2) () | ||
| 547 | (or cl-end1 (setq cl-end1 (length cl-seq1))) | ||
| 548 | (or cl-end2 (setq cl-end2 (length cl-seq2))) | ||
| 549 | (if cl-from-end | ||
| 550 | (progn | ||
| 551 | (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) | ||
| 552 | (cl-check-match (elt cl-seq1 (1- cl-end1)) | ||
| 553 | (elt cl-seq2 (1- cl-end2)))) | ||
| 554 | (setq cl-end1 (1- cl-end1) cl-end2 (1- cl-end2))) | ||
| 555 | (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) | ||
| 556 | (1- cl-end1))) | ||
| 557 | (let ((cl-p1 (and (listp cl-seq1) (nthcdr cl-start1 cl-seq1))) | ||
| 558 | (cl-p2 (and (listp cl-seq2) (nthcdr cl-start2 cl-seq2)))) | ||
| 559 | (while (and (< cl-start1 cl-end1) (< cl-start2 cl-end2) | ||
| 560 | (cl-check-match (if cl-p1 (car cl-p1) | ||
| 561 | (aref cl-seq1 cl-start1)) | ||
| 562 | (if cl-p2 (car cl-p2) | ||
| 563 | (aref cl-seq2 cl-start2)))) | ||
| 564 | (setq cl-p1 (cdr cl-p1) cl-p2 (cdr cl-p2) | ||
| 565 | cl-start1 (1+ cl-start1) cl-start2 (1+ cl-start2))) | ||
| 566 | (and (or (< cl-start1 cl-end1) (< cl-start2 cl-end2)) | ||
| 567 | cl-start1))))) | ||
| 568 | |||
| 569 | (defun search (cl-seq1 cl-seq2 &rest cl-keys) | ||
| 570 | "Search for SEQ1 as a subsequence of SEQ2. | ||
| 571 | Return the index of the leftmost element of the first match found; | ||
| 572 | return nil if there are no matches. | ||
| 573 | Keywords supported: :test :test-not :key :start1 :end1 :start2 :end2 :from-end" | ||
| 574 | (cl-parsing-keywords (:test :test-not :key :from-end | ||
| 575 | (:start1 0) :end1 (:start2 0) :end2) () | ||
| 576 | (or cl-end1 (setq cl-end1 (length cl-seq1))) | ||
| 577 | (or cl-end2 (setq cl-end2 (length cl-seq2))) | ||
| 578 | (if (>= cl-start1 cl-end1) | ||
| 579 | (if cl-from-end cl-end2 cl-start2) | ||
| 580 | (let* ((cl-len (- cl-end1 cl-start1)) | ||
| 581 | (cl-first (cl-check-key (elt cl-seq1 cl-start1))) | ||
| 582 | (cl-if nil) cl-pos) | ||
| 583 | (setq cl-end2 (- cl-end2 (1- cl-len))) | ||
| 584 | (while (and (< cl-start2 cl-end2) | ||
| 585 | (setq cl-pos (cl-position cl-first cl-seq2 | ||
| 586 | cl-start2 cl-end2 cl-from-end)) | ||
| 587 | (apply 'mismatch cl-seq1 cl-seq2 | ||
| 588 | ':start1 (1+ cl-start1) ':end1 cl-end1 | ||
| 589 | ':start2 (1+ cl-pos) ':end2 (+ cl-pos cl-len) | ||
| 590 | ':from-end nil cl-keys)) | ||
| 591 | (if cl-from-end (setq cl-end2 cl-pos) (setq cl-start2 (1+ cl-pos)))) | ||
| 592 | (and (< cl-start2 cl-end2) cl-pos))))) | ||
| 593 | |||
| 594 | (defun sort* (cl-seq cl-pred &rest cl-keys) | ||
| 595 | "Sort the argument SEQUENCE according to PREDICATE. | ||
| 596 | This is a destructive function; it reuses the storage of SEQUENCE if possible. | ||
| 597 | Keywords supported: :key" | ||
| 598 | (if (nlistp cl-seq) | ||
| 599 | (replace cl-seq (apply 'sort* (append cl-seq nil) cl-pred cl-keys)) | ||
| 600 | (cl-parsing-keywords (:key) () | ||
| 601 | (if (memq cl-key '(nil identity)) | ||
| 602 | (sort cl-seq cl-pred) | ||
| 603 | (sort cl-seq (function (lambda (cl-x cl-y) | ||
| 604 | (funcall cl-pred (funcall cl-key cl-x) | ||
| 605 | (funcall cl-key cl-y))))))))) | ||
| 606 | |||
| 607 | (defun stable-sort (cl-seq cl-pred &rest cl-keys) | ||
| 608 | "Sort the argument SEQUENCE stably according to PREDICATE. | ||
| 609 | This is a destructive function; it reuses the storage of SEQUENCE if possible. | ||
| 610 | Keywords supported: :key" | ||
| 611 | (apply 'sort* cl-seq cl-pred cl-keys)) | ||
| 612 | |||
| 613 | (defun merge (cl-type cl-seq1 cl-seq2 cl-pred &rest cl-keys) | ||
| 614 | "Destructively merge the two sequences to produce a new sequence. | ||
| 615 | TYPE is the sequence type to return, SEQ1 and SEQ2 are the two | ||
| 616 | argument sequences, and PRED is a `less-than' predicate on the elements. | ||
| 617 | Keywords supported: :key" | ||
| 618 | (or (listp cl-seq1) (setq cl-seq1 (append cl-seq1 nil))) | ||
| 619 | (or (listp cl-seq2) (setq cl-seq2 (append cl-seq2 nil))) | ||
| 620 | (cl-parsing-keywords (:key) () | ||
| 621 | (let ((cl-res nil)) | ||
| 622 | (while (and cl-seq1 cl-seq2) | ||
| 623 | (if (funcall cl-pred (cl-check-key (car cl-seq2)) | ||
| 624 | (cl-check-key (car cl-seq1))) | ||
| 625 | (cl-push (cl-pop cl-seq2) cl-res) | ||
| 626 | (cl-push (cl-pop cl-seq1) cl-res))) | ||
| 627 | (coerce (nconc (nreverse cl-res) cl-seq1 cl-seq2) cl-type)))) | ||
| 628 | |||
| 629 | ;;; See compiler macro in cl-macs.el | ||
| 630 | (defun member* (cl-item cl-list &rest cl-keys) | ||
| 631 | "Find the first occurrence of ITEM in LIST. | ||
| 632 | Return the sublist of LIST whose car is ITEM. | ||
| 633 | Keywords supported: :test :test-not :key" | ||
| 634 | (if cl-keys | ||
| 635 | (cl-parsing-keywords (:test :test-not :key :if :if-not) () | ||
| 636 | (while (and cl-list (not (cl-check-test cl-item (car cl-list)))) | ||
| 637 | (setq cl-list (cdr cl-list))) | ||
| 638 | cl-list) | ||
| 639 | (if (and (numberp cl-item) (not (integerp cl-item))) | ||
| 640 | (member cl-item cl-list) | ||
| 641 | (memq cl-item cl-list)))) | ||
| 642 | |||
| 643 | (defun member-if (cl-pred cl-list &rest cl-keys) | ||
| 644 | "Find the first item satisfying PREDICATE in LIST. | ||
| 645 | Return the sublist of LIST whose car matches. | ||
| 646 | Keywords supported: :key" | ||
| 647 | (apply 'member* nil cl-list ':if cl-pred cl-keys)) | ||
| 648 | |||
| 649 | (defun member-if-not (cl-pred cl-list &rest cl-keys) | ||
| 650 | "Find the first item not satisfying PREDICATE in LIST. | ||
| 651 | Return the sublist of LIST whose car matches. | ||
| 652 | Keywords supported: :key" | ||
| 653 | (apply 'member* nil cl-list ':if-not cl-pred cl-keys)) | ||
| 654 | |||
| 655 | (defun cl-adjoin (cl-item cl-list &rest cl-keys) | ||
| 656 | (if (cl-parsing-keywords (:key) t | ||
| 657 | (apply 'member* (cl-check-key cl-item) cl-list cl-keys)) | ||
| 658 | cl-list | ||
| 659 | (cons cl-item cl-list))) | ||
| 660 | |||
| 661 | ;;; See compiler macro in cl-macs.el | ||
| 662 | (defun assoc* (cl-item cl-alist &rest cl-keys) | ||
| 663 | "Find the first item whose car matches ITEM in LIST. | ||
| 664 | Keywords supported: :test :test-not :key" | ||
| 665 | (if cl-keys | ||
| 666 | (cl-parsing-keywords (:test :test-not :key :if :if-not) () | ||
| 667 | (while (and cl-alist | ||
| 668 | (or (not (consp (car cl-alist))) | ||
| 669 | (not (cl-check-test cl-item (car (car cl-alist)))))) | ||
| 670 | (setq cl-alist (cdr cl-alist))) | ||
| 671 | (and cl-alist (car cl-alist))) | ||
| 672 | (if (and (numberp cl-item) (not (integerp cl-item))) | ||
| 673 | (assoc cl-item cl-alist) | ||
| 674 | (assq cl-item cl-alist)))) | ||
| 675 | |||
| 676 | (defun assoc-if (cl-pred cl-list &rest cl-keys) | ||
| 677 | "Find the first item whose car satisfies PREDICATE in LIST. | ||
| 678 | Keywords supported: :key" | ||
| 679 | (apply 'assoc* nil cl-list ':if cl-pred cl-keys)) | ||
| 680 | |||
| 681 | (defun assoc-if-not (cl-pred cl-list &rest cl-keys) | ||
| 682 | "Find the first item whose car does not satisfy PREDICATE in LIST. | ||
| 683 | Keywords supported: :key" | ||
| 684 | (apply 'assoc* nil cl-list ':if-not cl-pred cl-keys)) | ||
| 685 | |||
| 686 | (defun rassoc* (cl-item cl-alist &rest cl-keys) | ||
| 687 | "Find the first item whose cdr matches ITEM in LIST. | ||
| 688 | Keywords supported: :test :test-not :key" | ||
| 689 | (if (or cl-keys (numberp cl-item)) | ||
| 690 | (cl-parsing-keywords (:test :test-not :key :if :if-not) () | ||
| 691 | (while (and cl-alist | ||
| 692 | (or (not (consp (car cl-alist))) | ||
| 693 | (not (cl-check-test cl-item (cdr (car cl-alist)))))) | ||
| 694 | (setq cl-alist (cdr cl-alist))) | ||
| 695 | (and cl-alist (car cl-alist))) | ||
| 696 | (rassq cl-item cl-alist))) | ||
| 697 | |||
| 698 | (defun rassoc (item alist) (rassoc* item alist ':test 'equal)) | ||
| 699 | |||
| 700 | (defun rassoc-if (cl-pred cl-list &rest cl-keys) | ||
| 701 | "Find the first item whose cdr satisfies PREDICATE in LIST. | ||
| 702 | Keywords supported: :key" | ||
| 703 | (apply 'rassoc* nil cl-list ':if cl-pred cl-keys)) | ||
| 704 | |||
| 705 | (defun rassoc-if-not (cl-pred cl-list &rest cl-keys) | ||
| 706 | "Find the first item whose cdr does not satisfy PREDICATE in LIST. | ||
| 707 | Keywords supported: :key" | ||
| 708 | (apply 'rassoc* nil cl-list ':if-not cl-pred cl-keys)) | ||
| 709 | |||
| 710 | (defun union (cl-list1 cl-list2 &rest cl-keys) | ||
| 711 | "Combine LIST1 and LIST2 using a set-union operation. | ||
| 712 | The result list contains all items that appear in either LIST1 or LIST2. | ||
| 713 | This is a non-destructive function; it makes a copy of the data if necessary | ||
| 714 | to avoid corrupting the original LIST1 and LIST2. | ||
| 715 | Keywords supported: :test :test-not :key" | ||
| 716 | (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) | ||
| 717 | ((equal cl-list1 cl-list2) cl-list1) | ||
| 718 | (t | ||
| 719 | (or (>= (length cl-list1) (length cl-list2)) | ||
| 720 | (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) | ||
| 721 | (while cl-list2 | ||
| 722 | (if (or cl-keys (numberp (car cl-list2))) | ||
| 723 | (setq cl-list1 (apply 'adjoin (car cl-list2) cl-list1 cl-keys)) | ||
| 724 | (or (memq (car cl-list2) cl-list1) | ||
| 725 | (cl-push (car cl-list2) cl-list1))) | ||
| 726 | (cl-pop cl-list2)) | ||
| 727 | cl-list1))) | ||
| 728 | |||
| 729 | (defun nunion (cl-list1 cl-list2 &rest cl-keys) | ||
| 730 | "Combine LIST1 and LIST2 using a set-union operation. | ||
| 731 | The result list contains all items that appear in either LIST1 or LIST2. | ||
| 732 | This is a destructive function; it reuses the storage of LIST1 and LIST2 | ||
| 733 | whenever possible. | ||
| 734 | Keywords supported: :test :test-not :key" | ||
| 735 | (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) | ||
| 736 | (t (apply 'union cl-list1 cl-list2 cl-keys)))) | ||
| 737 | |||
| 738 | (defun intersection (cl-list1 cl-list2 &rest cl-keys) | ||
| 739 | "Combine LIST1 and LIST2 using a set-intersection operation. | ||
| 740 | The result list contains all items that appear in both LIST1 and LIST2. | ||
| 741 | This is a non-destructive function; it makes a copy of the data if necessary | ||
| 742 | to avoid corrupting the original LIST1 and LIST2. | ||
| 743 | Keywords supported: :test :test-not :key" | ||
| 744 | (and cl-list1 cl-list2 | ||
| 745 | (if (equal cl-list1 cl-list2) cl-list1 | ||
| 746 | (cl-parsing-keywords (:key) (:test :test-not) | ||
| 747 | (let ((cl-res nil)) | ||
| 748 | (or (>= (length cl-list1) (length cl-list2)) | ||
| 749 | (setq cl-list1 (prog1 cl-list2 (setq cl-list2 cl-list1)))) | ||
| 750 | (while cl-list2 | ||
| 751 | (if (if (or cl-keys (numberp (car cl-list2))) | ||
| 752 | (apply 'member* (cl-check-key (car cl-list2)) | ||
| 753 | cl-list1 cl-keys) | ||
| 754 | (memq (car cl-list2) cl-list1)) | ||
| 755 | (cl-push (car cl-list2) cl-res)) | ||
| 756 | (cl-pop cl-list2)) | ||
| 757 | cl-res))))) | ||
| 758 | |||
| 759 | (defun nintersection (cl-list1 cl-list2 &rest cl-keys) | ||
| 760 | "Combine LIST1 and LIST2 using a set-intersection operation. | ||
| 761 | The result list contains all items that appear in both LIST1 and LIST2. | ||
| 762 | This is a destructive function; it reuses the storage of LIST1 and LIST2 | ||
| 763 | whenever possible. | ||
| 764 | Keywords supported: :test :test-not :key" | ||
| 765 | (and cl-list1 cl-list2 (apply 'intersection cl-list1 cl-list2 cl-keys))) | ||
| 766 | |||
| 767 | (defun set-difference (cl-list1 cl-list2 &rest cl-keys) | ||
| 768 | "Combine LIST1 and LIST2 using a set-difference operation. | ||
| 769 | The result list contains all items that appear in LIST1 but not LIST2. | ||
| 770 | This is a non-destructive function; it makes a copy of the data if necessary | ||
| 771 | to avoid corrupting the original LIST1 and LIST2. | ||
| 772 | Keywords supported: :test :test-not :key" | ||
| 773 | (if (or (null cl-list1) (null cl-list2)) cl-list1 | ||
| 774 | (cl-parsing-keywords (:key) (:test :test-not) | ||
| 775 | (let ((cl-res nil)) | ||
| 776 | (while cl-list1 | ||
| 777 | (or (if (or cl-keys (numberp (car cl-list1))) | ||
| 778 | (apply 'member* (cl-check-key (car cl-list1)) | ||
| 779 | cl-list2 cl-keys) | ||
| 780 | (memq (car cl-list1) cl-list2)) | ||
| 781 | (cl-push (car cl-list1) cl-res)) | ||
| 782 | (cl-pop cl-list1)) | ||
| 783 | cl-res)))) | ||
| 784 | |||
| 785 | (defun nset-difference (cl-list1 cl-list2 &rest cl-keys) | ||
| 786 | "Combine LIST1 and LIST2 using a set-difference operation. | ||
| 787 | The result list contains all items that appear in LIST1 but not LIST2. | ||
| 788 | This is a destructive function; it reuses the storage of LIST1 and LIST2 | ||
| 789 | whenever possible. | ||
| 790 | Keywords supported: :test :test-not :key" | ||
| 791 | (if (or (null cl-list1) (null cl-list2)) cl-list1 | ||
| 792 | (apply 'set-difference cl-list1 cl-list2 cl-keys))) | ||
| 793 | |||
| 794 | (defun set-exclusive-or (cl-list1 cl-list2 &rest cl-keys) | ||
| 795 | "Combine LIST1 and LIST2 using a set-exclusive-or operation. | ||
| 796 | The result list contains all items that appear in exactly one of LIST1, LIST2. | ||
| 797 | This is a non-destructive function; it makes a copy of the data if necessary | ||
| 798 | to avoid corrupting the original LIST1 and LIST2. | ||
| 799 | Keywords supported: :test :test-not :key" | ||
| 800 | (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) | ||
| 801 | ((equal cl-list1 cl-list2) nil) | ||
| 802 | (t (append (apply 'set-difference cl-list1 cl-list2 cl-keys) | ||
| 803 | (apply 'set-difference cl-list2 cl-list1 cl-keys))))) | ||
| 804 | |||
| 805 | (defun nset-exclusive-or (cl-list1 cl-list2 &rest cl-keys) | ||
| 806 | "Combine LIST1 and LIST2 using a set-exclusive-or operation. | ||
| 807 | The result list contains all items that appear in exactly one of LIST1, LIST2. | ||
| 808 | This is a destructive function; it reuses the storage of LIST1 and LIST2 | ||
| 809 | whenever possible. | ||
| 810 | Keywords supported: :test :test-not :key" | ||
| 811 | (cond ((null cl-list1) cl-list2) ((null cl-list2) cl-list1) | ||
| 812 | ((equal cl-list1 cl-list2) nil) | ||
| 813 | (t (nconc (apply 'nset-difference cl-list1 cl-list2 cl-keys) | ||
| 814 | (apply 'nset-difference cl-list2 cl-list1 cl-keys))))) | ||
| 815 | |||
| 816 | (defun subsetp (cl-list1 cl-list2 &rest cl-keys) | ||
| 817 | "True if LIST1 is a subset of LIST2. | ||
| 818 | I.e., if every element of LIST1 also appears in LIST2. | ||
| 819 | Keywords supported: :test :test-not :key" | ||
| 820 | (cond ((null cl-list1) t) ((null cl-list2) nil) | ||
| 821 | ((equal cl-list1 cl-list2) t) | ||
| 822 | (t (cl-parsing-keywords (:key) (:test :test-not) | ||
| 823 | (while (and cl-list1 | ||
| 824 | (apply 'member* (cl-check-key (car cl-list1)) | ||
| 825 | cl-list2 cl-keys)) | ||
| 826 | (cl-pop cl-list1)) | ||
| 827 | (null cl-list1))))) | ||
| 828 | |||
| 829 | (defun subst-if (cl-new cl-pred cl-tree &rest cl-keys) | ||
| 830 | "Substitute NEW for elements matching PREDICATE in TREE (non-destructively). | ||
| 831 | Return a copy of TREE with all matching elements replaced by NEW. | ||
| 832 | Keywords supported: :key" | ||
| 833 | (apply 'sublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) | ||
| 834 | |||
| 835 | (defun subst-if-not (cl-new cl-pred cl-tree &rest cl-keys) | ||
| 836 | "Substitute NEW for elts not matching PREDICATE in TREE (non-destructively). | ||
| 837 | Return a copy of TREE with all non-matching elements replaced by NEW. | ||
| 838 | Keywords supported: :key" | ||
| 839 | (apply 'sublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) | ||
| 840 | |||
| 841 | (defun nsubst (cl-new cl-old cl-tree &rest cl-keys) | ||
| 842 | "Substitute NEW for OLD everywhere in TREE (destructively). | ||
| 843 | Any element of TREE which is `eql' to OLD is changed to NEW (via a call | ||
| 844 | to `setcar'). | ||
| 845 | Keywords supported: :test :test-not :key" | ||
| 846 | (apply 'nsublis (list (cons cl-old cl-new)) cl-tree cl-keys)) | ||
| 847 | |||
| 848 | (defun nsubst-if (cl-new cl-pred cl-tree &rest cl-keys) | ||
| 849 | "Substitute NEW for elements matching PREDICATE in TREE (destructively). | ||
| 850 | Any element of TREE which matches is changed to NEW (via a call to `setcar'). | ||
| 851 | Keywords supported: :key" | ||
| 852 | (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if cl-pred cl-keys)) | ||
| 853 | |||
| 854 | (defun nsubst-if-not (cl-new cl-pred cl-tree &rest cl-keys) | ||
| 855 | "Substitute NEW for elements not matching PREDICATE in TREE (destructively). | ||
| 856 | Any element of TREE which matches is changed to NEW (via a call to `setcar'). | ||
| 857 | Keywords supported: :key" | ||
| 858 | (apply 'nsublis (list (cons nil cl-new)) cl-tree ':if-not cl-pred cl-keys)) | ||
| 859 | |||
| 860 | (defun sublis (cl-alist cl-tree &rest cl-keys) | ||
| 861 | "Perform substitutions indicated by ALIST in TREE (non-destructively). | ||
| 862 | Return a copy of TREE with all matching elements replaced. | ||
| 863 | Keywords supported: :test :test-not :key" | ||
| 864 | (cl-parsing-keywords (:test :test-not :key :if :if-not) () | ||
| 865 | (cl-sublis-rec cl-tree))) | ||
| 866 | |||
| 867 | (defvar cl-alist) | ||
| 868 | (defun cl-sublis-rec (cl-tree) ; uses cl-alist/key/test*/if* | ||
| 869 | (let ((cl-temp (cl-check-key cl-tree)) (cl-p cl-alist)) | ||
| 870 | (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) | ||
| 871 | (setq cl-p (cdr cl-p))) | ||
| 872 | (if cl-p (cdr (car cl-p)) | ||
| 873 | (if (consp cl-tree) | ||
| 874 | (let ((cl-a (cl-sublis-rec (car cl-tree))) | ||
| 875 | (cl-d (cl-sublis-rec (cdr cl-tree)))) | ||
| 876 | (if (and (eq cl-a (car cl-tree)) (eq cl-d (cdr cl-tree))) | ||
| 877 | cl-tree | ||
| 878 | (cons cl-a cl-d))) | ||
| 879 | cl-tree)))) | ||
| 880 | |||
| 881 | (defun nsublis (cl-alist cl-tree &rest cl-keys) | ||
| 882 | "Perform substitutions indicated by ALIST in TREE (destructively). | ||
| 883 | Any matching element of TREE is changed via a call to `setcar'. | ||
| 884 | Keywords supported: :test :test-not :key" | ||
| 885 | (cl-parsing-keywords (:test :test-not :key :if :if-not) () | ||
| 886 | (let ((cl-hold (list cl-tree))) | ||
| 887 | (cl-nsublis-rec cl-hold) | ||
| 888 | (car cl-hold)))) | ||
| 889 | |||
| 890 | (defun cl-nsublis-rec (cl-tree) ; uses cl-alist/temp/p/key/test*/if* | ||
| 891 | (while (consp cl-tree) | ||
| 892 | (let ((cl-temp (cl-check-key (car cl-tree))) (cl-p cl-alist)) | ||
| 893 | (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) | ||
| 894 | (setq cl-p (cdr cl-p))) | ||
| 895 | (if cl-p (setcar cl-tree (cdr (car cl-p))) | ||
| 896 | (if (consp (car cl-tree)) (cl-nsublis-rec (car cl-tree)))) | ||
| 897 | (setq cl-temp (cl-check-key (cdr cl-tree)) cl-p cl-alist) | ||
| 898 | (while (and cl-p (not (cl-check-test-nokey (car (car cl-p)) cl-temp))) | ||
| 899 | (setq cl-p (cdr cl-p))) | ||
| 900 | (if cl-p | ||
| 901 | (progn (setcdr cl-tree (cdr (car cl-p))) (setq cl-tree nil)) | ||
| 902 | (setq cl-tree (cdr cl-tree)))))) | ||
| 903 | |||
| 904 | (defun tree-equal (cl-x cl-y &rest cl-keys) | ||
| 905 | "T if trees X and Y have `eql' leaves. | ||
| 906 | Atoms are compared by `eql'; cons cells are compared recursively. | ||
| 907 | Keywords supported: :test :test-not :key" | ||
| 908 | (cl-parsing-keywords (:test :test-not :key) () | ||
| 909 | (cl-tree-equal-rec cl-x cl-y))) | ||
| 910 | |||
| 911 | (defun cl-tree-equal-rec (cl-x cl-y) | ||
| 912 | (while (and (consp cl-x) (consp cl-y) | ||
| 913 | (cl-tree-equal-rec (car cl-x) (car cl-y))) | ||
| 914 | (setq cl-x (cdr cl-x) cl-y (cdr cl-y))) | ||
| 915 | (and (not (consp cl-x)) (not (consp cl-y)) (cl-check-match cl-x cl-y))) | ||
| 916 | |||
| 917 | |||
| 918 | (run-hooks 'cl-seq-load-hook) | ||
| 919 | |||
| 920 | ;;; cl-seq.el ends here | ||
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el new file mode 100644 index 00000000000..41f0baaa6fd --- /dev/null +++ b/lisp/emacs-lisp/cl.el | |||
| @@ -0,0 +1,757 @@ | |||
| 1 | ;; cl.el --- Common Lisp extensions for GNU Emacs Lisp | ||
| 2 | |||
| 3 | ;; Copyright (C) 1993 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Dave Gillespie <daveg@synaptics.com> | ||
| 6 | ;; Version: 2.02 | ||
| 7 | ;; Keywords: extensions | ||
| 8 | |||
| 9 | ;; This file is part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 14 | ;; any later version. | ||
| 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 | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | |||
| 25 | ;; Commentary: | ||
| 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 | ;; | ||
| 34 | ;; This package works with Emacs 18, Emacs 19, and Lucid Emacs 19. | ||
| 35 | ;; | ||
| 36 | ;; Bug reports, comments, and suggestions are welcome! | ||
| 37 | |||
| 38 | ;; This file contains the portions of the Common Lisp extensions | ||
| 39 | ;; package which should always be present. | ||
| 40 | |||
| 41 | |||
| 42 | ;; Future notes: | ||
| 43 | |||
| 44 | ;; Once Emacs 19 becomes standard, many things in this package which are | ||
| 45 | ;; messy for reasons of compatibility can be greatly simplified. For now, | ||
| 46 | ;; I prefer to maintain one unified version. | ||
| 47 | |||
| 48 | |||
| 49 | ;; Change Log: | ||
| 50 | |||
| 51 | ;; Version 2.02 (30 Jul 93): | ||
| 52 | ;; * Added "cl-compat.el" file, extra compatibility with old package. | ||
| 53 | ;; * Added `lexical-let' and `lexical-let*'. | ||
| 54 | ;; * Added `define-modify-macro', `callf', and `callf2'. | ||
| 55 | ;; * Added `ignore-errors'. | ||
| 56 | ;; * Changed `(setf (nthcdr N PLACE) X)' to work when N is zero. | ||
| 57 | ;; * Merged `*gentemp-counter*' into `*gensym-counter*'. | ||
| 58 | ;; * Extended `subseq' to allow negative START and END like `substring'. | ||
| 59 | ;; * Added `in-ref', `across-ref', `elements of-ref' loop clauses. | ||
| 60 | ;; * Added `concat', `vconcat' loop clauses. | ||
| 61 | ;; * Cleaned up a number of compiler warnings. | ||
| 62 | |||
| 63 | ;; Version 2.01 (7 Jul 93): | ||
| 64 | ;; * Added support for FSF version of Emacs 19. | ||
| 65 | ;; * Added `add-hook' for Emacs 18 users. | ||
| 66 | ;; * Added `defsubst*' and `symbol-macrolet'. | ||
| 67 | ;; * Added `maplist', `mapc', `mapl', `mapcan', `mapcon'. | ||
| 68 | ;; * Added `map', `concatenate', `reduce', `merge'. | ||
| 69 | ;; * Added `revappend', `nreconc', `tailp', `tree-equal'. | ||
| 70 | ;; * Added `assert', `check-type', `typecase', `typep', and `deftype'. | ||
| 71 | ;; * Added destructuring and `&environment' support to `defmacro*'. | ||
| 72 | ;; * Added destructuring to `loop', and added the following clauses: | ||
| 73 | ;; `elements', `frames', `overlays', `intervals', `buffers', `key-seqs'. | ||
| 74 | ;; * Renamed `delete' to `delete*' and `remove' to `remove*'. | ||
| 75 | ;; * Completed support for all keywords in `remove*', `substitute', etc. | ||
| 76 | ;; * Added `most-positive-float' and company. | ||
| 77 | ;; * Fixed hash tables to work with latest Lucid Emacs. | ||
| 78 | ;; * `proclaim' forms are no longer compile-time-evaluating; use `declaim'. | ||
| 79 | ;; * Syntax for `warn' declarations has changed. | ||
| 80 | ;; * Improved implementation of `random*'. | ||
| 81 | ;; * Moved most sequence functions to a new file, cl-seq.el. | ||
| 82 | ;; * Moved `eval-when' into cl-macs.el. | ||
| 83 | ;; * Moved `pushnew' and `adjoin' to cl.el for most common cases. | ||
| 84 | ;; * Moved `provide' forms down to ends of files. | ||
| 85 | ;; * Changed expansion of `pop' to something that compiles to better code. | ||
| 86 | ;; * Changed so that no patch is required for Emacs 19 byte compiler. | ||
| 87 | ;; * Made more things dependent on `optimize' declarations. | ||
| 88 | ;; * Added a partial implementation of struct print functions. | ||
| 89 | ;; * Miscellaneous minor changes. | ||
| 90 | |||
| 91 | ;; Version 2.00: | ||
| 92 | ;; * First public release of this package. | ||
| 93 | |||
| 94 | |||
| 95 | ;; Code: | ||
| 96 | |||
| 97 | (defvar cl-emacs-type (cond ((or (and (fboundp 'epoch::version) | ||
| 98 | (symbol-value 'epoch::version)) | ||
| 99 | (string-lessp emacs-version "19")) 18) | ||
| 100 | ((string-match "Lucid" emacs-version) 'lucid) | ||
| 101 | (t 19))) | ||
| 102 | |||
| 103 | (or (fboundp 'defalias) (fset 'defalias 'fset)) | ||
| 104 | |||
| 105 | (defvar cl-optimize-speed 1) | ||
| 106 | (defvar cl-optimize-safety 1) | ||
| 107 | |||
| 108 | |||
| 109 | ;;; Keywords used in this package. | ||
| 110 | |||
| 111 | (defconst :test ':test) | ||
| 112 | (defconst :test-not ':test-not) | ||
| 113 | (defconst :key ':key) | ||
| 114 | (defconst :start ':start) | ||
| 115 | (defconst :start1 ':start1) | ||
| 116 | (defconst :start2 ':start2) | ||
| 117 | (defconst :end ':end) | ||
| 118 | (defconst :end1 ':end1) | ||
| 119 | (defconst :end2 ':end2) | ||
| 120 | (defconst :count ':count) | ||
| 121 | (defconst :initial-value ':initial-value) | ||
| 122 | (defconst :size ':size) | ||
| 123 | (defconst :from-end ':from-end) | ||
| 124 | (defconst :rehash-size ':rehash-size) | ||
| 125 | (defconst :rehash-threshold ':rehash-threshold) | ||
| 126 | (defconst :allow-other-keys ':allow-other-keys) | ||
| 127 | |||
| 128 | |||
| 129 | (defvar custom-print-functions nil | ||
| 130 | "This is a list of functions that format user objects for printing. | ||
| 131 | Each function is called in turn with three arguments: the object, the | ||
| 132 | stream, and the print level (currently ignored). If it is able to | ||
| 133 | print the object it returns true; otherwise it returns nil and the | ||
| 134 | printer proceeds to the next function on the list. | ||
| 135 | |||
| 136 | This variable is not used at present, but it is defined in hopes that | ||
| 137 | a future Emacs interpreter will be able to use it.") | ||
| 138 | |||
| 139 | |||
| 140 | ;;; Predicates. | ||
| 141 | |||
| 142 | (defun eql (a b) ; See compiler macro in cl-macs.el | ||
| 143 | "T if the two args are the same Lisp object. | ||
| 144 | Floating-point numbers of equal value are `eql', but they may not be `eq'." | ||
| 145 | (if (numberp a) | ||
| 146 | (equal a b) | ||
| 147 | (eq a b))) | ||
| 148 | |||
| 149 | |||
| 150 | ;;; Generalized variables. These macros are defined here so that they | ||
| 151 | ;;; can safely be used in .emacs files. | ||
| 152 | |||
| 153 | (defmacro incf (place &optional x) | ||
| 154 | "(incf PLACE [X]): increment PLACE by X (1 by default). | ||
| 155 | PLACE may be a symbol, or any generalized variable allowed by `setf'. | ||
| 156 | The return value is the incremented value of PLACE." | ||
| 157 | (if (symbolp place) | ||
| 158 | (list 'setq place (if x (list '+ place x) (list '1+ place))) | ||
| 159 | (list 'callf '+ place (or x 1)))) | ||
| 160 | |||
| 161 | (defmacro decf (place &optional x) | ||
| 162 | "(decf PLACE [X]): decrement PLACE by X (1 by default). | ||
| 163 | PLACE may be a symbol, or any generalized variable allowed by `setf'. | ||
| 164 | The return value is the decremented value of PLACE." | ||
| 165 | (if (symbolp place) | ||
| 166 | (list 'setq place (if x (list '- place x) (list '1- place))) | ||
| 167 | (list 'callf '- place (or x 1)))) | ||
| 168 | |||
| 169 | (defmacro pop (place) | ||
| 170 | "(pop PLACE): remove and return the head of the list stored in PLACE. | ||
| 171 | Analogous to (prog1 (car PLACE) (setf PLACE (cdr PLACE))), though more | ||
| 172 | careful about evaluating each argument only once and in the right order. | ||
| 173 | PLACE may be a symbol, or any generalized variable allowed by `setf'." | ||
| 174 | (if (symbolp place) | ||
| 175 | (list 'car (list 'prog1 place (list 'setq place (list 'cdr place)))) | ||
| 176 | (cl-do-pop place))) | ||
| 177 | |||
| 178 | (defmacro push (x place) | ||
| 179 | "(push X PLACE): insert X at the head of the list stored in PLACE. | ||
| 180 | Analogous to (setf PLACE (cons X PLACE)), though more careful about | ||
| 181 | evaluating each argument only once and in the right order. PLACE may | ||
| 182 | be a symbol, or any generalized variable allowed by `setf'." | ||
| 183 | (if (symbolp place) (list 'setq place (list 'cons x place)) | ||
| 184 | (list 'callf2 'cons x place))) | ||
| 185 | |||
| 186 | (defmacro pushnew (x place &rest keys) | ||
| 187 | "(pushnew X PLACE): insert X at the head of the list if not already there. | ||
| 188 | Like (push X PLACE), except that the list is unmodified if X is `eql' to | ||
| 189 | an element already on the list. | ||
| 190 | Keywords supported: :test :test-not :key" | ||
| 191 | (if (symbolp place) (list 'setq place (list* 'adjoin x place keys)) | ||
| 192 | (list* 'callf2 'adjoin x place keys))) | ||
| 193 | |||
| 194 | (defun cl-set-elt (seq n val) | ||
| 195 | (if (listp seq) (setcar (nthcdr n seq) val) (aset seq n val))) | ||
| 196 | |||
| 197 | (defun cl-set-nthcdr (n list x) | ||
| 198 | (if (<= n 0) x (setcdr (nthcdr (1- n) list) x) list)) | ||
| 199 | |||
| 200 | (defun cl-set-buffer-substring (start end val) | ||
| 201 | (save-excursion (delete-region start end) | ||
| 202 | (goto-char start) | ||
| 203 | (insert val) | ||
| 204 | val)) | ||
| 205 | |||
| 206 | (defun cl-set-substring (str start end val) | ||
| 207 | (if end (if (< end 0) (incf end (length str))) | ||
| 208 | (setq end (length str))) | ||
| 209 | (if (< start 0) (incf start str)) | ||
| 210 | (concat (and (> start 0) (substring str 0 start)) | ||
| 211 | val | ||
| 212 | (and (< end (length str)) (substring str end)))) | ||
| 213 | |||
| 214 | |||
| 215 | ;;; Control structures. | ||
| 216 | |||
| 217 | ;;; These macros are so simple and so often-used that it's better to have | ||
| 218 | ;;; them all the time than to load them from cl-macs.el. | ||
| 219 | |||
| 220 | (defmacro when (cond &rest body) | ||
| 221 | "(when COND BODY...): if COND yields non-nil, do BODY, else return nil." | ||
| 222 | (list 'if cond (cons 'progn body))) | ||
| 223 | |||
| 224 | (defmacro unless (cond &rest body) | ||
| 225 | "(unless COND BODY...): if COND yields nil, do BODY, else return nil." | ||
| 226 | (cons 'if (cons cond (cons nil body)))) | ||
| 227 | |||
| 228 | (defun cl-map-extents (&rest cl-args) | ||
| 229 | (if (fboundp 'next-overlay-at) (apply 'cl-map-overlays cl-args) | ||
| 230 | (if (fboundp 'map-extents) (apply 'map-extents cl-args)))) | ||
| 231 | |||
| 232 | |||
| 233 | ;;; Blocks and exits. | ||
| 234 | |||
| 235 | (defalias 'cl-block-wrapper 'identity) | ||
| 236 | (defalias 'cl-block-throw 'throw) | ||
| 237 | |||
| 238 | |||
| 239 | ;;; Multiple values. True multiple values are not supported, or even | ||
| 240 | ;;; simulated. Instead, multiple-value-bind and friends simply expect | ||
| 241 | ;;; the target form to return the values as a list. | ||
| 242 | |||
| 243 | (defalias 'values 'list) | ||
| 244 | (defalias 'values-list 'identity) | ||
| 245 | (defalias 'multiple-value-list 'identity) | ||
| 246 | (defalias 'multiple-value-call 'apply) ; only works for one arg | ||
| 247 | (defalias 'nth-value 'nth) | ||
| 248 | |||
| 249 | |||
| 250 | ;;; Macros. | ||
| 251 | |||
| 252 | (defvar cl-macro-environment nil) | ||
| 253 | (defvar cl-old-macroexpand (prog1 (symbol-function 'macroexpand) | ||
| 254 | (defalias 'macroexpand 'cl-macroexpand))) | ||
| 255 | |||
| 256 | (defun cl-macroexpand (cl-macro &optional cl-env) | ||
| 257 | (let ((cl-macro-environment cl-env)) | ||
| 258 | (while (progn (setq cl-macro (funcall cl-old-macroexpand cl-macro cl-env)) | ||
| 259 | (and (symbolp cl-macro) | ||
| 260 | (cdr (assq (symbol-name cl-macro) cl-env)))) | ||
| 261 | (setq cl-macro (cadr (assq (symbol-name cl-macro) cl-env)))) | ||
| 262 | cl-macro)) | ||
| 263 | |||
| 264 | |||
| 265 | ;;; Declarations. | ||
| 266 | |||
| 267 | (defvar cl-compiling-file nil) | ||
| 268 | (defun cl-compiling-file () | ||
| 269 | (or cl-compiling-file | ||
| 270 | (and (boundp 'outbuffer) (bufferp (symbol-value 'outbuffer)) | ||
| 271 | (equal (buffer-name (symbol-value 'outbuffer)) | ||
| 272 | " *Compiler Output*")))) | ||
| 273 | |||
| 274 | (defvar cl-proclaims-deferred nil) | ||
| 275 | |||
| 276 | (defun proclaim (spec) | ||
| 277 | (if (fboundp 'cl-do-proclaim) (cl-do-proclaim spec t) | ||
| 278 | (push spec cl-proclaims-deferred)) | ||
| 279 | nil) | ||
| 280 | |||
| 281 | (defmacro declaim (&rest specs) | ||
| 282 | (let ((body (mapcar (function (lambda (x) (list 'proclaim (list 'quote x)))) | ||
| 283 | specs))) | ||
| 284 | (if (cl-compiling-file) (list* 'eval-when '(compile load eval) body) | ||
| 285 | (cons 'progn body)))) ; avoid loading cl-macs.el for eval-when | ||
| 286 | |||
| 287 | |||
| 288 | ;;; Symbols. | ||
| 289 | |||
| 290 | (defun cl-random-time () | ||
| 291 | (let* ((time (copy-sequence (current-time-string))) (i (length time)) (v 0)) | ||
| 292 | (while (>= (decf i) 0) (setq v (+ (* v 3) (aref time i)))) | ||
| 293 | v)) | ||
| 294 | |||
| 295 | (defvar *gensym-counter* (* (logand (cl-random-time) 1023) 100)) | ||
| 296 | |||
| 297 | |||
| 298 | ;;; Numbers. | ||
| 299 | |||
| 300 | (defun floatp-safe (x) | ||
| 301 | "T if OBJECT is a floating point number. | ||
| 302 | On Emacs versions that lack floating-point support, this function | ||
| 303 | always returns nil." | ||
| 304 | (and (numberp x) (not (integerp x)))) | ||
| 305 | |||
| 306 | (defun plusp (x) | ||
| 307 | "T if NUMBER is positive." | ||
| 308 | (> x 0)) | ||
| 309 | |||
| 310 | (defun minusp (x) | ||
| 311 | "T if NUMBER is negative." | ||
| 312 | (< x 0)) | ||
| 313 | |||
| 314 | (defun oddp (x) | ||
| 315 | "T if INTEGER is odd." | ||
| 316 | (eq (logand x 1) 1)) | ||
| 317 | |||
| 318 | (defun evenp (x) | ||
| 319 | "T if INTEGER is even." | ||
| 320 | (eq (logand x 1) 0)) | ||
| 321 | |||
| 322 | (defun cl-abs (x) | ||
| 323 | "Return the absolute value of ARG." | ||
| 324 | (if (>= x 0) x (- x))) | ||
| 325 | (or (fboundp 'abs) (defalias 'abs 'cl-abs)) ; This is built-in to Emacs 19 | ||
| 326 | |||
| 327 | (defvar *random-state* (vector 'cl-random-state-tag -1 30 (cl-random-time))) | ||
| 328 | |||
| 329 | ;;; We use `eval' in case VALBITS differs from compile-time to load-time. | ||
| 330 | (defconst most-positive-fixnum (eval '(lsh -1 -1))) | ||
| 331 | (defconst most-negative-fixnum (eval '(- -1 (lsh -1 -1)))) | ||
| 332 | |||
| 333 | ;;; The following are actually set by cl-float-limits. | ||
| 334 | (defconst most-positive-float nil) | ||
| 335 | (defconst most-negative-float nil) | ||
| 336 | (defconst least-positive-float nil) | ||
| 337 | (defconst least-negative-float nil) | ||
| 338 | (defconst least-positive-normalized-float nil) | ||
| 339 | (defconst least-negative-normalized-float nil) | ||
| 340 | (defconst float-epsilon nil) | ||
| 341 | (defconst float-negative-epsilon nil) | ||
| 342 | |||
| 343 | |||
| 344 | ;;; Sequence functions. | ||
| 345 | |||
| 346 | (defalias 'copy-seq 'copy-sequence) | ||
| 347 | |||
| 348 | (defun mapcar* (cl-func cl-x &rest cl-rest) | ||
| 349 | "Apply FUNCTION to each element of SEQ, and make a list of the results. | ||
| 350 | If there are several SEQs, FUNCTION is called with that many arguments, | ||
| 351 | and mapping stops as soon as the shortest list runs out. With just one | ||
| 352 | SEQ, this is like `mapcar'. With several, it is like the Common Lisp | ||
| 353 | `mapcar' function extended to arbitrary sequence types." | ||
| 354 | (if cl-rest | ||
| 355 | (if (or (cdr cl-rest) (nlistp cl-x) (nlistp (car cl-rest))) | ||
| 356 | (cl-mapcar-many cl-func (cons cl-x cl-rest)) | ||
| 357 | (let ((cl-res nil) (cl-y (car cl-rest))) | ||
| 358 | (while (and cl-x cl-y) | ||
| 359 | (push (funcall cl-func (pop cl-x) (pop cl-y)) cl-res)) | ||
| 360 | (nreverse cl-res))) | ||
| 361 | (mapcar cl-func cl-x))) | ||
| 362 | |||
| 363 | |||
| 364 | ;;; List functions. | ||
| 365 | |||
| 366 | (defalias 'first 'car) | ||
| 367 | (defalias 'rest 'cdr) | ||
| 368 | (defalias 'endp 'null) | ||
| 369 | |||
| 370 | (defun second (x) | ||
| 371 | "Return the second element of the list LIST." | ||
| 372 | (car (cdr x))) | ||
| 373 | |||
| 374 | (defun third (x) | ||
| 375 | "Return the third element of the list LIST." | ||
| 376 | (car (cdr (cdr x)))) | ||
| 377 | |||
| 378 | (defun fourth (x) | ||
| 379 | "Return the fourth element of the list LIST." | ||
| 380 | (nth 3 x)) | ||
| 381 | |||
| 382 | (defun fifth (x) | ||
| 383 | "Return the fifth element of the list LIST." | ||
| 384 | (nth 4 x)) | ||
| 385 | |||
| 386 | (defun sixth (x) | ||
| 387 | "Return the sixth element of the list LIST." | ||
| 388 | (nth 5 x)) | ||
| 389 | |||
| 390 | (defun seventh (x) | ||
| 391 | "Return the seventh element of the list LIST." | ||
| 392 | (nth 6 x)) | ||
| 393 | |||
| 394 | (defun eighth (x) | ||
| 395 | "Return the eighth element of the list LIST." | ||
| 396 | (nth 7 x)) | ||
| 397 | |||
| 398 | (defun ninth (x) | ||
| 399 | "Return the ninth element of the list LIST." | ||
| 400 | (nth 8 x)) | ||
| 401 | |||
| 402 | (defun tenth (x) | ||
| 403 | "Return the tenth element of the list LIST." | ||
| 404 | (nth 9 x)) | ||
| 405 | |||
| 406 | (defun caar (x) | ||
| 407 | "Return the `car' of the `car' of X." | ||
| 408 | (car (car x))) | ||
| 409 | |||
| 410 | (defun cadr (x) | ||
| 411 | "Return the `car' of the `cdr' of X." | ||
| 412 | (car (cdr x))) | ||
| 413 | |||
| 414 | (defun cdar (x) | ||
| 415 | "Return the `cdr' of the `car' of X." | ||
| 416 | (cdr (car x))) | ||
| 417 | |||
| 418 | (defun cddr (x) | ||
| 419 | "Return the `cdr' of the `cdr' of X." | ||
| 420 | (cdr (cdr x))) | ||
| 421 | |||
| 422 | (defun caaar (x) | ||
| 423 | "Return the `car' of the `car' of the `car' of X." | ||
| 424 | (car (car (car x)))) | ||
| 425 | |||
| 426 | (defun caadr (x) | ||
| 427 | "Return the `car' of the `car' of the `cdr' of X." | ||
| 428 | (car (car (cdr x)))) | ||
| 429 | |||
| 430 | (defun cadar (x) | ||
| 431 | "Return the `car' of the `cdr' of the `car' of X." | ||
| 432 | (car (cdr (car x)))) | ||
| 433 | |||
| 434 | (defun caddr (x) | ||
| 435 | "Return the `car' of the `cdr' of the `cdr' of X." | ||
| 436 | (car (cdr (cdr x)))) | ||
| 437 | |||
| 438 | (defun cdaar (x) | ||
| 439 | "Return the `cdr' of the `car' of the `car' of X." | ||
| 440 | (cdr (car (car x)))) | ||
| 441 | |||
| 442 | (defun cdadr (x) | ||
| 443 | "Return the `cdr' of the `car' of the `cdr' of X." | ||
| 444 | (cdr (car (cdr x)))) | ||
| 445 | |||
| 446 | (defun cddar (x) | ||
| 447 | "Return the `cdr' of the `cdr' of the `car' of X." | ||
| 448 | (cdr (cdr (car x)))) | ||
| 449 | |||
| 450 | (defun cdddr (x) | ||
| 451 | "Return the `cdr' of the `cdr' of the `cdr' of X." | ||
| 452 | (cdr (cdr (cdr x)))) | ||
| 453 | |||
| 454 | (defun caaaar (x) | ||
| 455 | "Return the `car' of the `car' of the `car' of the `car' of X." | ||
| 456 | (car (car (car (car x))))) | ||
| 457 | |||
| 458 | (defun caaadr (x) | ||
| 459 | "Return the `car' of the `car' of the `car' of the `cdr' of X." | ||
| 460 | (car (car (car (cdr x))))) | ||
| 461 | |||
| 462 | (defun caadar (x) | ||
| 463 | "Return the `car' of the `car' of the `cdr' of the `car' of X." | ||
| 464 | (car (car (cdr (car x))))) | ||
| 465 | |||
| 466 | (defun caaddr (x) | ||
| 467 | "Return the `car' of the `car' of the `cdr' of the `cdr' of X." | ||
| 468 | (car (car (cdr (cdr x))))) | ||
| 469 | |||
| 470 | (defun cadaar (x) | ||
| 471 | "Return the `car' of the `cdr' of the `car' of the `car' of X." | ||
| 472 | (car (cdr (car (car x))))) | ||
| 473 | |||
| 474 | (defun cadadr (x) | ||
| 475 | "Return the `car' of the `cdr' of the `car' of the `cdr' of X." | ||
| 476 | (car (cdr (car (cdr x))))) | ||
| 477 | |||
| 478 | (defun caddar (x) | ||
| 479 | "Return the `car' of the `cdr' of the `cdr' of the `car' of X." | ||
| 480 | (car (cdr (cdr (car x))))) | ||
| 481 | |||
| 482 | (defun cadddr (x) | ||
| 483 | "Return the `car' of the `cdr' of the `cdr' of the `cdr' of X." | ||
| 484 | (car (cdr (cdr (cdr x))))) | ||
| 485 | |||
| 486 | (defun cdaaar (x) | ||
| 487 | "Return the `cdr' of the `car' of the `car' of the `car' of X." | ||
| 488 | (cdr (car (car (car x))))) | ||
| 489 | |||
| 490 | (defun cdaadr (x) | ||
| 491 | "Return the `cdr' of the `car' of the `car' of the `cdr' of X." | ||
| 492 | (cdr (car (car (cdr x))))) | ||
| 493 | |||
| 494 | (defun cdadar (x) | ||
| 495 | "Return the `cdr' of the `car' of the `cdr' of the `car' of X." | ||
| 496 | (cdr (car (cdr (car x))))) | ||
| 497 | |||
| 498 | (defun cdaddr (x) | ||
| 499 | "Return the `cdr' of the `car' of the `cdr' of the `cdr' of X." | ||
| 500 | (cdr (car (cdr (cdr x))))) | ||
| 501 | |||
| 502 | (defun cddaar (x) | ||
| 503 | "Return the `cdr' of the `cdr' of the `car' of the `car' of X." | ||
| 504 | (cdr (cdr (car (car x))))) | ||
| 505 | |||
| 506 | (defun cddadr (x) | ||
| 507 | "Return the `cdr' of the `cdr' of the `car' of the `cdr' of X." | ||
| 508 | (cdr (cdr (car (cdr x))))) | ||
| 509 | |||
| 510 | (defun cdddar (x) | ||
| 511 | "Return the `cdr' of the `cdr' of the `cdr' of the `car' of X." | ||
| 512 | (cdr (cdr (cdr (car x))))) | ||
| 513 | |||
| 514 | (defun cddddr (x) | ||
| 515 | "Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X." | ||
| 516 | (cdr (cdr (cdr (cdr x))))) | ||
| 517 | |||
| 518 | (defun last (x &optional n) | ||
| 519 | "Returns the last link in the list LIST. | ||
| 520 | With optional argument N, returns Nth-to-last link (default 1)." | ||
| 521 | (if n | ||
| 522 | (let ((m 0) (p x)) | ||
| 523 | (while (consp p) (incf m) (pop p)) | ||
| 524 | (if (<= n 0) p | ||
| 525 | (if (< n m) (nthcdr (- m n) x) x))) | ||
| 526 | (while (consp (cdr x)) (pop x)) | ||
| 527 | x)) | ||
| 528 | |||
| 529 | (defun butlast (x &optional n) | ||
| 530 | "Returns a copy of LIST with the last N elements removed." | ||
| 531 | (if (and n (<= n 0)) x | ||
| 532 | (nbutlast (copy-sequence x) n))) | ||
| 533 | |||
| 534 | (defun nbutlast (x &optional n) | ||
| 535 | "Modifies LIST to remove the last N elements." | ||
| 536 | (let ((m (length x))) | ||
| 537 | (or n (setq n 1)) | ||
| 538 | (and (< n m) | ||
| 539 | (progn | ||
| 540 | (if (> n 0) (setcdr (nthcdr (- (1- m) n) x) nil)) | ||
| 541 | x)))) | ||
| 542 | |||
| 543 | (defun list* (arg &rest rest) ; See compiler macro in cl-macs.el | ||
| 544 | "Return a new list with specified args as elements, cons'd to last arg. | ||
| 545 | Thus, `(list* A B C D)' is equivalent to `(nconc (list A B C) D)', or to | ||
| 546 | `(cons A (cons B (cons C D)))'." | ||
| 547 | (cond ((not rest) arg) | ||
| 548 | ((not (cdr rest)) (cons arg (car rest))) | ||
| 549 | (t (let* ((n (length rest)) | ||
| 550 | (copy (copy-sequence rest)) | ||
| 551 | (last (nthcdr (- n 2) copy))) | ||
| 552 | (setcdr last (car (cdr last))) | ||
| 553 | (cons arg copy))))) | ||
| 554 | |||
| 555 | (defun ldiff (list sublist) | ||
| 556 | "Return a copy of LIST with the tail SUBLIST removed." | ||
| 557 | (let ((res nil)) | ||
| 558 | (while (and (consp list) (not (eq list sublist))) | ||
| 559 | (push (pop list) res)) | ||
| 560 | (nreverse res))) | ||
| 561 | |||
| 562 | (defun copy-list (list) | ||
| 563 | "Return a copy of a list, which may be a dotted list. | ||
| 564 | The elements of the list are not copied, just the list structure itself." | ||
| 565 | (if (consp list) | ||
| 566 | (let ((res nil)) | ||
| 567 | (while (consp list) (push (pop list) res)) | ||
| 568 | (prog1 (nreverse res) (setcdr res list))) | ||
| 569 | (car list))) | ||
| 570 | |||
| 571 | (defun cl-maclisp-member (item list) | ||
| 572 | (while (and list (not (equal item (car list)))) (setq list (cdr list))) | ||
| 573 | list) | ||
| 574 | |||
| 575 | ;;; Define an Emacs 19-compatible `member' for the benefit of Emacs 18 users. | ||
| 576 | (or (and (fboundp 'member) (subrp (symbol-function 'member))) | ||
| 577 | (defalias 'member 'cl-maclisp-member)) | ||
| 578 | |||
| 579 | (defalias 'cl-member 'memq) ; for compatibility with old CL package | ||
| 580 | (defalias 'cl-floor 'floor*) | ||
| 581 | (defalias 'cl-ceiling 'ceiling*) | ||
| 582 | (defalias 'cl-truncate 'truncate*) | ||
| 583 | (defalias 'cl-round 'round*) | ||
| 584 | (defalias 'cl-mod 'mod*) | ||
| 585 | |||
| 586 | (defun adjoin (cl-item cl-list &rest cl-keys) ; See compiler macro in cl-macs | ||
| 587 | "Return ITEM consed onto the front of LIST only if it's not already there. | ||
| 588 | Otherwise, return LIST unmodified. | ||
| 589 | Keywords supported: :test :test-not :key" | ||
| 590 | (cond ((or (equal cl-keys '(:test eq)) | ||
| 591 | (and (null cl-keys) (not (numberp cl-item)))) | ||
| 592 | (if (memq cl-item cl-list) cl-list (cons cl-item cl-list))) | ||
| 593 | ((or (equal cl-keys '(:test equal)) (null cl-keys)) | ||
| 594 | (if (member cl-item cl-list) cl-list (cons cl-item cl-list))) | ||
| 595 | (t (apply 'cl-adjoin cl-item cl-list cl-keys)))) | ||
| 596 | |||
| 597 | (defun subst (cl-new cl-old cl-tree &rest cl-keys) | ||
| 598 | "Substitute NEW for OLD everywhere in TREE (non-destructively). | ||
| 599 | Return a copy of TREE with all elements `eql' to OLD replaced by NEW. | ||
| 600 | Keywords supported: :test :test-not :key" | ||
| 601 | (if (or cl-keys (and (numberp cl-old) (not (integerp cl-old)))) | ||
| 602 | (apply 'sublis (list (cons cl-old cl-new)) cl-tree cl-keys) | ||
| 603 | (cl-do-subst cl-new cl-old cl-tree))) | ||
| 604 | |||
| 605 | (defun cl-do-subst (cl-new cl-old cl-tree) | ||
| 606 | (cond ((eq cl-tree cl-old) cl-new) | ||
| 607 | ((consp cl-tree) | ||
| 608 | (let ((a (cl-do-subst cl-new cl-old (car cl-tree))) | ||
| 609 | (d (cl-do-subst cl-new cl-old (cdr cl-tree)))) | ||
| 610 | (if (and (eq a (car cl-tree)) (eq d (cdr cl-tree))) | ||
| 611 | cl-tree (cons a d)))) | ||
| 612 | (t cl-tree))) | ||
| 613 | |||
| 614 | (defun acons (a b c) (cons (cons a b) c)) | ||
| 615 | (defun pairlis (a b &optional c) (nconc (mapcar* 'cons a b) c)) | ||
| 616 | |||
| 617 | |||
| 618 | ;;; Miscellaneous. | ||
| 619 | |||
| 620 | (put 'cl-assertion-failed 'error-conditions '(error)) | ||
| 621 | (put 'cl-assertion-failed 'error-message "Assertion failed") | ||
| 622 | |||
| 623 | ;;; This is defined in Emacs 19; define it here for Emacs 18 users. | ||
| 624 | (defun cl-add-hook (hook func &optional append) | ||
| 625 | "Add to hook variable HOOK the function FUNC. | ||
| 626 | FUNC is not added if it already appears on the list stored in HOOK." | ||
| 627 | (let ((old (and (boundp hook) (symbol-value hook)))) | ||
| 628 | (and (listp old) (not (eq (car old) 'lambda)) | ||
| 629 | (setq old (list old))) | ||
| 630 | (and (not (member func old)) | ||
| 631 | (set hook (if append (nconc old (list func)) (cons func old)))))) | ||
| 632 | (or (fboundp 'add-hook) (defalias 'add-hook 'cl-add-hook)) | ||
| 633 | |||
| 634 | |||
| 635 | ;;; Autoload the other portions of the package. | ||
| 636 | (mapcar (function | ||
| 637 | (lambda (set) | ||
| 638 | (mapcar (function | ||
| 639 | (lambda (func) | ||
| 640 | (autoload func (car set) nil nil (nth 1 set)))) | ||
| 641 | (cddr set)))) | ||
| 642 | '(("cl-extra" nil | ||
| 643 | coerce equalp cl-map-keymap maplist mapc mapl mapcan mapcon | ||
| 644 | cl-map-keymap cl-map-keymap-recursively cl-map-intervals | ||
| 645 | cl-map-overlays cl-set-frame-visible-p cl-float-limits | ||
| 646 | gcd lcm isqrt expt floor* ceiling* truncate* round* | ||
| 647 | mod* rem* signum random* make-random-state random-state-p | ||
| 648 | subseq concatenate cl-mapcar-many map some every notany | ||
| 649 | notevery revappend nreconc list-length tailp copy-tree get* getf | ||
| 650 | cl-set-getf cl-do-remf remprop make-hash-table cl-hash-lookup | ||
| 651 | gethash cl-puthash remhash clrhash maphash hash-table-p | ||
| 652 | hash-table-count cl-progv-before cl-prettyexpand | ||
| 653 | cl-macroexpand-all) | ||
| 654 | ("cl-seq" nil | ||
| 655 | reduce fill replace remq remove remove* remove-if remove-if-not | ||
| 656 | delete delete* delete-if delete-if-not remove-duplicates | ||
| 657 | delete-duplicates substitute substitute-if substitute-if-not | ||
| 658 | nsubstitute nsubstitute-if nsubstitute-if-not find find-if | ||
| 659 | find-if-not position position-if position-if-not count count-if | ||
| 660 | count-if-not mismatch search sort* stable-sort merge member* | ||
| 661 | member-if member-if-not cl-adjoin assoc* assoc-if assoc-if-not | ||
| 662 | rassoc* rassoc rassoc-if rassoc-if-not union nunion intersection | ||
| 663 | nintersection set-difference nset-difference set-exclusive-or | ||
| 664 | nset-exclusive-or subsetp subst-if subst-if-not nsubst nsubst-if | ||
| 665 | nsubst-if-not sublis nsublis tree-equal) | ||
| 666 | ("cl-macs" nil | ||
| 667 | gensym gentemp typep cl-do-pop get-setf-method | ||
| 668 | cl-struct-setf-expander compiler-macroexpand cl-compile-time-init) | ||
| 669 | ("cl-macs" t | ||
| 670 | defun* defmacro* function* destructuring-bind eval-when | ||
| 671 | eval-when-compile load-time-value case ecase typecase etypecase | ||
| 672 | block return return-from loop do do* dolist dotimes do-symbols | ||
| 673 | do-all-symbols psetq progv flet labels macrolet symbol-macrolet | ||
| 674 | lexical-let lexical-let* multiple-value-bind multiple-value-setq | ||
| 675 | locally the declare define-setf-method defsetf define-modify-macro | ||
| 676 | setf psetf remf shiftf rotatef letf letf* callf callf2 defstruct | ||
| 677 | check-type assert ignore-errors define-compiler-macro))) | ||
| 678 | |||
| 679 | ;;; Define data for indentation and edebug. | ||
| 680 | (mapcar (function | ||
| 681 | (lambda (entry) | ||
| 682 | (mapcar (function | ||
| 683 | (lambda (func) | ||
| 684 | (put func 'lisp-indent-function (nth 1 entry)) | ||
| 685 | (put func 'lisp-indent-hook (nth 1 entry)) | ||
| 686 | (or (get func 'edebug-form-spec) | ||
| 687 | (put func 'edebug-form-spec (nth 2 entry))))) | ||
| 688 | (car entry)))) | ||
| 689 | '(((defun* defmacro*) 2) | ||
| 690 | ((function*) nil | ||
| 691 | (&or symbolp ([&optional 'macro] 'lambda (&rest sexp) &rest form))) | ||
| 692 | ((eval-when) 1 (sexp &rest form)) | ||
| 693 | ((when unless) 1 (&rest form)) | ||
| 694 | ((declare) nil (&rest sexp)) | ||
| 695 | ((the) 1 (sexp &rest form)) | ||
| 696 | ((case ecase typecase etypecase) 1 (form &rest (sexp &rest form))) | ||
| 697 | ((block return-from) 1 (sexp &rest form)) | ||
| 698 | ((return) nil (&optional form)) | ||
| 699 | ((do do*) 2 ((&rest &or symbolp (symbolp &optional form form)) | ||
| 700 | (form &rest form) | ||
| 701 | &rest form)) | ||
| 702 | ((dolist dotimes) 1 ((symbolp form &rest form) &rest form)) | ||
| 703 | ((do-symbols) 1 ((symbolp form &optional form form) &rest form)) | ||
| 704 | ((do-all-symbols) 1 ((symbolp form &optional form) &rest form)) | ||
| 705 | ((psetq setf psetf) nil edebug-setq-form) | ||
| 706 | ((progv) 2 (&rest form)) | ||
| 707 | ((flet labels macrolet) 1 | ||
| 708 | ((&rest (sexp sexp &rest form)) &rest form)) | ||
| 709 | ((symbol-macrolet lexical-let lexical-let*) 1 | ||
| 710 | ((&rest &or symbolp (symbolp form)) &rest form)) | ||
| 711 | ((multiple-value-bind) 2 ((&rest symbolp) &rest form)) | ||
| 712 | ((multiple-value-setq) 1 ((&rest symbolp) &rest form)) | ||
| 713 | ((incf decf remf pop push pushnew shiftf rotatef) nil (&rest form)) | ||
| 714 | ((letf letf*) 1 ((&rest (&rest form)) &rest form)) | ||
| 715 | ((callf destructuring-bind) 2 (sexp form &rest form)) | ||
| 716 | ((callf2) 3 (sexp form form &rest form)) | ||
| 717 | ((loop) nil (&rest &or symbolp form)) | ||
| 718 | ((ignore-errors) 0 (&rest form)))) | ||
| 719 | |||
| 720 | |||
| 721 | ;;; This goes here so that cl-macs can find it if it loads right now. | ||
| 722 | (provide 'cl-19) ; usage: (require 'cl-19 "cl") | ||
| 723 | |||
| 724 | |||
| 725 | ;;; Things to do after byte-compiler is loaded. | ||
| 726 | ;;; As a side effect, we cause cl-macs to be loaded when compiling, so | ||
| 727 | ;;; that the compiler-macros defined there will be present. | ||
| 728 | |||
| 729 | (defvar cl-hacked-flag nil) | ||
| 730 | (defun cl-hack-byte-compiler () | ||
| 731 | (if (and (not cl-hacked-flag) (fboundp 'byte-compile-file-form)) | ||
| 732 | (progn | ||
| 733 | (cl-compile-time-init) ; in cl-macs.el | ||
| 734 | (setq cl-hacked-flag t)))) | ||
| 735 | |||
| 736 | ;;; Try it now in case the compiler has already been loaded. | ||
| 737 | (cl-hack-byte-compiler) | ||
| 738 | |||
| 739 | ;;; Also make a hook in case compiler is loaded after this file. | ||
| 740 | ;;; The compiler doesn't call any hooks when it loads or runs, but | ||
| 741 | ;;; we can take advantage of the fact that emacs-lisp-mode will be | ||
| 742 | ;;; called when the compiler reads in the file to be compiled. | ||
| 743 | ;;; BUG: If the first compilation is `byte-compile' rather than | ||
| 744 | ;;; `byte-compile-file', we lose. Oh, well. | ||
| 745 | (add-hook 'emacs-lisp-mode-hook 'cl-hack-byte-compiler) | ||
| 746 | |||
| 747 | |||
| 748 | ;;; The following ensures that packages which expect the old-style cl.el | ||
| 749 | ;;; will be happy with this one. | ||
| 750 | |||
| 751 | (provide 'cl) | ||
| 752 | |||
| 753 | (provide 'mini-cl) ; for Epoch | ||
| 754 | |||
| 755 | (run-hooks 'cl-load-hook) | ||
| 756 | |||
| 757 | ;;; cl.el ends here | ||