| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
(or (memq 'cl-19 features) |
|---|
| 49 |
(error "Tried to load `cl-macs' before `cl'!")) |
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
(defmacro cl-pop2 (place) |
|---|
| 53 |
(list 'prog1 (list 'car (list 'cdr place)) |
|---|
| 54 |
(list 'setq place (list 'cdr (list 'cdr place))))) |
|---|
| 55 |
(put 'cl-pop2 'edebug-form-spec 'edebug-sexps) |
|---|
| 56 |
|
|---|
| 57 |
(defvar cl-optimize-safety) |
|---|
| 58 |
(defvar cl-optimize-speed) |
|---|
| 59 |
|
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
|
|---|
| 64 |
(require |
|---|
| 65 |
(progn |
|---|
| 66 |
(or (fboundp 'cl-transform-function-property) |
|---|
| 67 |
(defalias 'cl-transform-function-property |
|---|
| 68 |
(function (lambda (n p f) |
|---|
| 69 |
(list 'put (list 'quote n) (list 'quote p) |
|---|
| 70 |
(list 'function (cons 'lambda f))))))) |
|---|
| 71 |
(car (or features (setq features (list 'cl-kludge)))))) |
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 |
(defvar cl-old-bc-file-form nil) |
|---|
| 77 |
|
|---|
| 78 |
(defun cl-compile-time-init () |
|---|
| 79 |
(run-hooks 'cl-hack-bytecomp-hook)) |
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
|
|---|
| 83 |
|
|---|
| 84 |
|
|---|
| 85 |
(defconst cl-simple-funcs '(car cdr nth aref elt if and or + - 1+ 1- min max |
|---|
| 86 |
car-safe cdr-safe progn prog1 prog2)) |
|---|
| 87 |
(defconst cl-safe-funcs '(* / % length memq list vector vectorp |
|---|
| 88 |
< > <= >= = error)) |
|---|
| 89 |
|
|---|
| 90 |
|
|---|
| 91 |
(defun cl-simple-expr-p (x &optional size) |
|---|
| 92 |
(or size (setq size 10)) |
|---|
| 93 |
(if (and (consp x) (not (memq (car x) '(quote function function*)))) |
|---|
| 94 |
(and (symbolp (car x)) |
|---|
| 95 |
(or (memq (car x) cl-simple-funcs) |
|---|
| 96 |
(get (car x) 'side-effect-free)) |
|---|
| 97 |
(progn |
|---|
| 98 |
(setq size (1- size)) |
|---|
| 99 |
(while (and (setq x (cdr x)) |
|---|
| 100 |
(setq size (cl-simple-expr-p (car x) size)))) |
|---|
| 101 |
(and (null x) (>= size 0) size))) |
|---|
| 102 |
(and (> size 0) (1- size)))) |
|---|
| 103 |
|
|---|
| 104 |
(defun cl-simple-exprs-p (xs) |
|---|
| 105 |
(while (and xs (cl-simple-expr-p (car xs))) |
|---|
| 106 |
(setq xs (cdr xs))) |
|---|
| 107 |
(not xs)) |
|---|
| 108 |
|
|---|
| 109 |
|
|---|
| 110 |
(defun cl-safe-expr-p (x) |
|---|
| 111 |
(or (not (and (consp x) (not (memq (car x) '(quote function function*))))) |
|---|
| 112 |
(and (symbolp (car x)) |
|---|
| 113 |
(or (memq (car x) cl-simple-funcs) |
|---|
| 114 |
(memq (car x) cl-safe-funcs) |
|---|
| 115 |
(get (car x) 'side-effect-free)) |
|---|
| 116 |
(progn |
|---|
| 117 |
(while (and (setq x (cdr x)) (cl-safe-expr-p (car x)))) |
|---|
| 118 |
(null x))))) |
|---|
| 119 |
|
|---|
| 120 |
|
|---|
| 121 |
(defun cl-const-expr-p (x) |
|---|
| 122 |
(cond ((consp x) |
|---|
| 123 |
(or (eq (car x) 'quote) |
|---|
| 124 |
(and (memq (car x) '(function function*)) |
|---|
| 125 |
(or (symbolp (nth 1 x)) |
|---|
| 126 |
(and (eq (car-safe (nth 1 x)) 'lambda) 'func))))) |
|---|
| 127 |
((symbolp x) (and (memq x '(nil t)) t)) |
|---|
| 128 |
(t t))) |
|---|
| 129 |
|
|---|
| 130 |
(defun cl-const-exprs-p (xs) |
|---|
| 131 |
(while (and xs (cl-const-expr-p (car xs))) |
|---|
| 132 |
(setq xs (cdr xs))) |
|---|
| 133 |
(not xs)) |
|---|
| 134 |
|
|---|
| 135 |
(defun cl-const-expr-val (x) |
|---|
| 136 |
(and (eq (cl-const-expr-p x) t) (if (consp x) (nth 1 x) x))) |
|---|
| 137 |
|
|---|
| 138 |
(defun cl-expr-access-order (x v) |
|---|
| 139 |
(if (cl-const-expr-p x) v |
|---|
| 140 |
(if (consp x) |
|---|
| 141 |
(progn |
|---|
| 142 |
(while (setq x (cdr x)) (setq v (cl-expr-access-order (car x) v))) |
|---|
| 143 |
v) |
|---|
| 144 |
(if (eq x (car v)) (cdr v) '(t))))) |
|---|
| 145 |
|
|---|
| 146 |
|
|---|
| 147 |
(defun cl-expr-contains (x y) |
|---|
| 148 |
(cond ((equal y x) 1) |
|---|
| 149 |
((and (consp x) (not (memq (car-safe x) '(quote function function*)))) |
|---|
| 150 |
(let ((sum 0)) |
|---|
| 151 |
(while x |
|---|
| 152 |
(setq sum (+ sum (or (cl-expr-contains (pop x) y) 0)))) |
|---|
| 153 |
(and (> sum 0) sum))) |
|---|
| 154 |
(t nil))) |
|---|
| 155 |
|
|---|
| 156 |
(defun cl-expr-contains-any (x y) |
|---|
| 157 |
(while (and y (not (cl-expr-contains x (car y)))) (pop y)) |
|---|
| 158 |
y) |
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 |
(defun cl-expr-depends-p (x y) |
|---|
| 162 |
(and (not (cl-const-expr-p x)) |
|---|
| 163 |
(or (not (cl-safe-expr-p x)) (cl-expr-contains-any x y)))) |
|---|
| 164 |
|
|---|
| 165 |
|
|---|
| 166 |
|
|---|
| 167 |
(defvar *gensym-counter*) |
|---|
| 168 |
(defun gensym (&optional prefix) |
|---|
| 169 |
"Generate a new uninterned symbol. |
|---|
| 170 |
The name is made by appending a number to PREFIX, default \"G\"." |
|---|
| 171 |
(let ((pfix (if (stringp prefix) prefix "G")) |
|---|
| 172 |
(num (if (integerp prefix) prefix |
|---|
| 173 |
(prog1 *gensym-counter* |
|---|
| 174 |
(setq *gensym-counter* (1+ *gensym-counter*)))))) |
|---|
| 175 |
(make-symbol (format "%s%d" pfix num)))) |
|---|
| 176 |
|
|---|
| 177 |
(defun gentemp (&optional prefix) |
|---|
| 178 |
"Generate a new interned symbol with a unique name. |
|---|
| 179 |
The name is made by appending a number to PREFIX, default \"G\"." |
|---|
| 180 |
(let ((pfix (if (stringp prefix) prefix "G")) |
|---|
| 181 |
name) |
|---|
| 182 |
(while (intern-soft (setq name (format "%s%d" pfix *gensym-counter*))) |
|---|
| 183 |
(setq *gensym-counter* (1+ *gensym-counter*))) |
|---|
| 184 |
(intern name))) |
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 |
|
|---|
| 188 |
|
|---|
| 189 |
(defmacro defun* (name args &rest body) |
|---|
| 190 |
"Define NAME as a function. |
|---|
| 191 |
Like normal `defun', except ARGLIST allows full Common Lisp conventions, |
|---|
| 192 |
and BODY is implicitly surrounded by (block NAME ...). |
|---|
| 193 |
|
|---|
| 194 |
\(fn NAME ARGLIST [DOCSTRING] BODY...)" |
|---|
| 195 |
(let* ((res (cl-transform-lambda (cons args body) name)) |
|---|
| 196 |
(form (list* 'defun name (cdr res)))) |
|---|
| 197 |
(if (car res) (list 'progn (car res) form) form))) |
|---|
| 198 |
|
|---|
| 199 |
(defmacro defmacro* (name args &rest body) |
|---|
| 200 |
"Define NAME as a macro. |
|---|
| 201 |
Like normal `defmacro', except ARGLIST allows full Common Lisp conventions, |
|---|
| 202 |
and BODY is implicitly surrounded by (block NAME ...). |
|---|
| 203 |
|
|---|
| 204 |
\(fn NAME ARGLIST [DOCSTRING] BODY...)" |
|---|
| 205 |
(let* ((res (cl-transform-lambda (cons args body) name)) |
|---|
| 206 |
(form (list* 'defmacro name (cdr res)))) |
|---|
| 207 |
(if (car res) (list 'progn (car res) form) form))) |
|---|
| 208 |
|
|---|
| 209 |
(defmacro function* (func) |
|---|
| 210 |
"Introduce a function. |
|---|
| 211 |
Like normal `function', except that if argument is a lambda form, |
|---|
| 212 |
its argument list allows full Common Lisp conventions." |
|---|
| 213 |
(if (eq (car-safe func) 'lambda) |
|---|
| 214 |
(let* ((res (cl-transform-lambda (cdr func) 'cl-none)) |
|---|
| 215 |
(form (list 'function (cons 'lambda (cdr res))))) |
|---|
| 216 |
(if (car res) (list 'progn (car res) form) form)) |
|---|
| 217 |
(list 'function func))) |
|---|
| 218 |
|
|---|
| 219 |
(defun cl-transform-function-property (func prop form) |
|---|
| 220 |
(let ((res (cl-transform-lambda form func))) |
|---|
| 221 |
(append '(progn) (cdr (cdr (car res))) |
|---|
| 222 |
(list (list 'put (list 'quote func) (list 'quote prop) |
|---|
| 223 |
(list 'function (cons 'lambda (cdr res)))))))) |
|---|
| 224 |
|
|---|
| 225 |
(defconst lambda-list-keywords |
|---|
| 226 |
'(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) |
|---|
| 227 |
|
|---|
| 228 |
(defvar cl-macro-environment nil) |
|---|
| 229 |
(defvar bind-block) (defvar bind-defs) (defvar bind-enquote) |
|---|
| 230 |
(defvar bind-inits) (defvar bind-lets) (defvar bind-forms) |
|---|
| 231 |
|
|---|
| 232 |
(defun cl-transform-lambda (form bind-block) |
|---|
| 233 |
(let* ((args (car form)) (body (cdr form)) (orig-args args) |
|---|
| 234 |
(bind-defs nil) (bind-enquote nil) |
|---|
| 235 |
(bind-inits nil) (bind-lets nil) (bind-forms nil) |
|---|
| 236 |
(header nil) (simple-args nil)) |
|---|
| 237 |
(while (or (stringp (car body)) |
|---|
| 238 |
(memq (car-safe (car body)) '(interactive declare))) |
|---|
| 239 |
(push (pop body) header)) |
|---|
| 240 |
(setq args (if (listp args) (copy-list args) (list '&rest args))) |
|---|
| 241 |
(let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) |
|---|
| 242 |
(if (setq bind-defs (cadr (memq '&cl-defs args))) |
|---|
| 243 |
(setq args (delq '&cl-defs (delq bind-defs args)) |
|---|
| 244 |
bind-defs (cadr bind-defs))) |
|---|
| 245 |
(if (setq bind-enquote (memq '&cl-quote args)) |
|---|
| 246 |
(setq args (delq '&cl-quote args))) |
|---|
| 247 |
(if (memq '&whole args) (error "&whole not currently implemented")) |
|---|
| 248 |
(let* ((p (memq '&environment args)) (v (cadr p))) |
|---|
| 249 |
(if p (setq args (nconc (delq (car p) (delq v args)) |
|---|
| 250 |
(list '&aux (list v 'cl-macro-environment)))))) |
|---|
| 251 |
(while (and args (symbolp (car args)) |
|---|
| 252 |
(not (memq (car args) '(nil &rest &body &key &aux))) |
|---|
| 253 |
(not (and (eq (car args) '&optional) |
|---|
| 254 |
(or bind-defs (consp (cadr args)))))) |
|---|
| 255 |
(push (pop args) simple-args)) |
|---|
| 256 |
(or (eq bind-block 'cl-none) |
|---|
| 257 |
(setq body (list (list* 'block bind-block body)))) |
|---|
| 258 |
(if (null args) |
|---|
| 259 |
(list* nil (nreverse simple-args) (nconc (nreverse header) body)) |
|---|
| 260 |
(if (memq '&optional simple-args) (push '&optional args)) |
|---|
| 261 |
(cl-do-arglist args nil (- (length simple-args) |
|---|
| 262 |
(if (memq '&optional simple-args) 1 0))) |
|---|
| 263 |
(setq bind-lets (nreverse bind-lets)) |
|---|
| 264 |
(list* (and bind-inits (list* 'eval-when '(compile load eval) |
|---|
| 265 |
(nreverse bind-inits))) |
|---|
| 266 |
(nconc (nreverse simple-args) |
|---|
| 267 |
(list '&rest (car (pop bind-lets)))) |
|---|
| 268 |
(nconc (let ((hdr (nreverse header))) |
|---|
| 269 |
|
|---|
| 270 |
|
|---|
| 271 |
|
|---|
| 272 |
(save-match-data |
|---|
| 273 |
(require 'help-fns) |
|---|
| 274 |
(cons (help-add-fundoc-usage |
|---|
| 275 |
(if (stringp (car hdr)) (pop hdr)) |
|---|
| 276 |
|
|---|
| 277 |
|
|---|
| 278 |
(let ((x (memq '&cl-defs orig-args))) |
|---|
| 279 |
(if (null x) orig-args |
|---|
| 280 |
(delq (car x) (remq (cadr x) orig-args))))) |
|---|
| 281 |
hdr))) |
|---|
| 282 |
(list (nconc (list 'let* bind-lets) |
|---|
| 283 |
(nreverse bind-forms) body))))))) |
|---|
| 284 |
|
|---|
| 285 |
(defun cl-do-arglist (args expr &optional num) |
|---|
| 286 |
(if (nlistp args) |
|---|
| 287 |
(if (or (memq args lambda-list-keywords) (not (symbolp args))) |
|---|
| 288 |
(error "Invalid argument name: %s" args) |
|---|
| 289 |
(push (list args expr) bind-lets)) |
|---|
| 290 |
(setq args (copy-list args)) |
|---|
| 291 |
(let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) |
|---|
| 292 |
(let ((p (memq '&body args))) (if p (setcar p '&rest))) |
|---|
| 293 |
(if (memq '&environment args) (error "&environment used incorrectly")) |
|---|
| 294 |
(let ((save-args args) |
|---|
| 295 |
(restarg (memq '&rest args)) |
|---|
| 296 |
(safety (if (cl-compiling-file) cl-optimize-safety 3)) |
|---|
| 297 |
(keys nil) |
|---|
| 298 |
(laterarg nil) (exactarg nil) minarg) |
|---|
| 299 |
(or num (setq num 0)) |
|---|
| 300 |
(if (listp (cadr restarg)) |
|---|
| 301 |
(setq restarg (make-symbol "--cl-rest--")) |
|---|
| 302 |
(setq restarg (cadr restarg))) |
|---|
| 303 |
(push (list restarg expr) bind-lets) |
|---|
| 304 |
(if (eq (car args) '&whole) |
|---|
| 305 |
(push (list (cl-pop2 args) restarg) bind-lets)) |
|---|
| 306 |
(let ((p args)) |
|---|
| 307 |
(setq minarg restarg) |
|---|
| 308 |
(while (and p (not (memq (car p) lambda-list-keywords))) |
|---|
| 309 |
(or (eq p args) (setq minarg (list 'cdr minarg))) |
|---|
| 310 |
(setq p (cdr p))) |
|---|
| 311 |
(if (memq (car p) '(nil &aux)) |
|---|
| 312 |
(setq minarg (list '= (list 'length restarg) |
|---|
| 313 |
(length (ldiff args p))) |
|---|
| 314 |
exactarg (not (eq args p))))) |
|---|
| 315 |
(while (and args (not (memq (car args) lambda-list-keywords))) |
|---|
| 316 |
(let ((poparg (list (if (or (cdr args) (not exactarg)) 'pop 'car) |
|---|
| 317 |
restarg))) |
|---|
| 318 |
(cl-do-arglist |
|---|
| 319 |
(pop args) |
|---|
| 320 |
(if (or laterarg (= safety 0)) poparg |
|---|
| 321 |
(list 'if minarg poparg |
|---|
| 322 |
(list 'signal '(quote wrong-number-of-arguments) |
|---|
| 323 |
(list 'list (and (not (eq bind-block 'cl-none)) |
|---|
| 324 |
(list 'quote bind-block)) |
|---|
| 325 |
(list 'length restarg))))))) |
|---|
| 326 |
(setq num (1+ num) laterarg t)) |
|---|
| 327 |
(while (and (eq (car args) '&optional) (pop args)) |
|---|
| 328 |
(while (and args (not (memq (car args) lambda-list-keywords))) |
|---|
| 329 |
(let ((arg (pop args))) |
|---|
| 330 |
(or (consp arg) (setq arg (list arg))) |
|---|
| 331 |
(if (cddr arg) (cl-do-arglist (nth 2 arg) (list 'and restarg t))) |
|---|
| 332 |
(let ((def (if (cdr arg) (nth 1 arg) |
|---|
| 333 |
(or (car bind-defs) |
|---|
| 334 |
(nth 1 (assq (car arg) bind-defs))))) |
|---|
| 335 |
(poparg (list 'pop restarg))) |
|---|
| 336 |
(and def bind-enquote (setq def (list 'quote def))) |
|---|
| 337 |
(cl-do-arglist (car arg) |
|---|
| 338 |
(if def (list 'if restarg poparg def) poparg)) |
|---|
| 339 |
(setq num (1+ num)))))) |
|---|
| 340 |
(if (eq (car args) '&rest) |
|---|
| 341 |
(let ((arg (cl-pop2 args))) |
|---|
| 342 |
(if (consp arg) (cl-do-arglist arg restarg))) |
|---|
| 343 |
(or (eq (car args) '&key) (= safety 0) exactarg |
|---|
| 344 |
(push (list 'if restarg |
|---|
| 345 |
(list 'signal '(quote wrong-number-of-arguments) |
|---|
| 346 |
(list 'list |
|---|
| 347 |
(and (not (eq bind-block 'cl-none)) |
|---|
| 348 |
(list 'quote bind-block)) |
|---|
| 349 |
(list '+ num (list 'length restarg))))) |
|---|
| 350 |
bind-forms))) |
|---|
| 351 |
(while (and (eq (car args) '&key) (pop args)) |
|---|
| 352 |
(while (and args (not (memq (car args) lambda-list-keywords))) |
|---|
| 353 |
(let ((arg (pop args))) |
|---|
| 354 |
(or (consp arg) (setq arg (list arg))) |
|---|
| 355 |
(let* ((karg (if (consp (car arg)) (caar arg) |
|---|
| 356 |
(intern (format ":%s" (car arg))))) |
|---|
| 357 |
(varg (if (consp (car arg)) (cadar arg) (car arg))) |
|---|
| 358 |
(def (if (cdr arg) (cadr arg) |
|---|
| 359 |
(or (car bind-defs) (cadr (assq varg bind-defs))))) |
|---|
| 360 |
(look (list 'memq (list 'quote karg) restarg))) |
|---|
| 361 |
(and def bind-enquote (setq def (list 'quote def))) |
|---|
| 362 |
(if (cddr arg) |
|---|
| 363 |
(let* ((temp (or (nth 2 arg) (make-symbol "--cl-var--"))) |
|---|
| 364 |
(val (list 'car (list 'cdr temp)))) |
|---|
| 365 |
(cl-do-arglist temp look) |
|---|
| 366 |
(cl-do-arglist varg |
|---|
| 367 |
(list 'if temp |
|---|
| 368 |
(list 'prog1 val (list 'setq temp t)) |
|---|
| 369 |
def))) |
|---|
| 370 |
(cl-do-arglist |
|---|
| 371 |
varg |
|---|
| 372 |
(list 'car |
|---|
| 373 |
(list 'cdr |
|---|
| 374 |
(if (null def) |
|---|
| 375 |
look |
|---|
| 376 |
(list 'or look |
|---|
| 377 |
(if (eq (cl-const-expr-p def) t) |
|---|
| 378 |
(list |
|---|
| 379 |
'quote |
|---|
| 380 |
(list nil (cl-const-expr-val def))) |
|---|
| 381 |
(list 'list nil def)))))))) |
|---|
| 382 |
(push karg keys))))) |
|---|
| 383 |
(setq keys (nreverse keys)) |
|---|
| 384 |
(or (and (eq (car args) '&allow-other-keys) (pop args)) |
|---|
| 385 |
(null keys) (= safety 0) |
|---|
| 386 |
(let* ((var (make-symbol "--cl-keys--")) |
|---|
| 387 |
(allow '(:allow-other-keys)) |
|---|
| 388 |
(check (list |
|---|
| 389 |
'while var |
|---|
| 390 |
(list |
|---|
| 391 |
'cond |
|---|
| 392 |
(list (list 'memq (list 'car var) |
|---|
| 393 |
(list 'quote (append keys allow))) |
|---|
| 394 |
(list 'setq var (list 'cdr (list 'cdr var)))) |
|---|
| 395 |
(list (list 'car |
|---|
| 396 |
(list 'cdr |
|---|
| 397 |
(list 'memq (cons 'quote allow) |
|---|
| 398 |
restarg))) |
|---|
| 399 |
(list 'setq var nil)) |
|---|
| 400 |
(list t |
|---|
| 401 |
(list |
|---|
| 402 |
'error |
|---|
| 403 |
(format "Keyword argument %%s not one of %s" |
|---|
| 404 |
keys) |
|---|
| 405 |
(list 'car var))))))) |
|---|
| 406 |
(push (list 'let (list (list var restarg)) check) bind-forms))) |
|---|
| 407 |
(while (and (eq (car args) '&aux) (pop args)) |
|---|
| 408 |
(while (and args (not (memq (car args) lambda-list-keywords))) |
|---|
| 409 |
(if (consp (car args)) |
|---|
| 410 |
(if (and bind-enquote (cadar args)) |
|---|
| 411 |
(cl-do-arglist (caar args) |
|---|
| 412 |
(list 'quote (cadr (pop args)))) |
|---|
| 413 |
(cl-do-arglist (caar args) (cadr (pop args)))) |
|---|
| 414 |
(cl-do-arglist (pop args) nil)))) |
|---|
| 415 |
(if args (error "Malformed argument list %s" save-args))))) |
|---|
| 416 |
|
|---|
| 417 |
(defun cl-arglist-args (args) |
|---|
| 418 |
(if (nlistp args) (list args) |
|---|
| 419 |
(let ((res nil) (kind nil) arg) |
|---|
| 420 |
(while (consp args) |
|---|
| 421 |
(setq arg (pop args)) |
|---|
| 422 |
(if (memq arg lambda-list-keywords) (setq kind arg) |
|---|
| 423 |
(if (eq arg '&cl-defs) (pop args) |
|---|
| 424 |
(and (consp arg) kind (setq arg (car arg))) |
|---|
| 425 |
(and (consp arg) (cdr arg) (eq kind '&key) (setq arg (cadr arg))) |
|---|
| 426 |
(setq res (nconc res (cl-arglist-args arg)))))) |
|---|
| 427 |
(nconc res (and args (list args)))))) |
|---|
| 428 |
|
|---|
| 429 |
(defmacro destructuring-bind (args expr &rest body) |
|---|
| 430 |
(let* ((bind-lets nil) (bind-forms nil) (bind-inits nil) |
|---|
| 431 |
(bind-defs nil) (bind-block 'cl-none)) |
|---|
| 432 |
(cl-do-arglist (or args '(&aux)) expr) |
|---|
| 433 |
(append '(progn) bind-inits |
|---|
| 434 |
(list (nconc (list 'let* (nreverse bind-lets)) |
|---|
| 435 |
(nreverse bind-forms) body))))) |
|---|
| 436 |
|
|---|
| 437 |
|
|---|
| 438 |
|
|---|
| 439 |
|
|---|
| 440 |
(defvar cl-not-toplevel nil) |
|---|
| 441 |
|
|---|
| 442 |
(defmacro eval-when (when &rest body) |
|---|
| 443 |
"Control when BODY is evaluated. |
|---|
| 444 |
If `compile' is in WHEN, BODY is evaluated when compiled at top-level. |
|---|
| 445 |
If `load' is in WHEN, BODY is evaluated when loaded after top-level compile. |
|---|
| 446 |
If `eval' is in WHEN, BODY is evaluated when interpreted or at non-top-level. |
|---|
| 447 |
|
|---|
| 448 |
\(fn (WHEN...) BODY...)" |
|---|
| 449 |
(if (and (fboundp 'cl-compiling-file) (cl-compiling-file) |
|---|
| 450 |
(not cl-not-toplevel) (not (boundp 'for-effect))) |
|---|
| 451 |
(let ((comp (or (memq 'compile when) (memq :compile-toplevel when))) |
|---|
| 452 |
(cl-not-toplevel t)) |
|---|
| 453 |
(if (or (memq 'load when) (memq :load-toplevel when)) |
|---|
| 454 |
(if comp (cons 'progn (mapcar 'cl-compile-time-too body)) |
|---|
| 455 |
(list* 'if nil nil body)) |
|---|
| 456 |
(progn (if comp (eval (cons 'progn body))) nil))) |
|---|
| 457 |
(and (or (memq 'eval when) (memq :execute when)) |
|---|
| 458 |
(cons 'progn body)))) |
|---|
| 459 |
|
|---|
| 460 |
(defun cl-compile-time-too (form) |
|---|
| 461 |
(or (and (symbolp (car-safe form)) (get (car-safe form) 'byte-hunk-handler)) |
|---|
| 462 |
(setq form (macroexpand |
|---|
| 463 |
form (cons '(eval-when) byte-compile-macro-environment)))) |
|---|
| 464 |
(cond ((eq (car-safe form) 'progn) |
|---|
| 465 |
(cons 'progn (mapcar 'cl-compile-time-too (cdr form)))) |
|---|
| 466 |
((eq (car-safe form) 'eval-when) |
|---|
| 467 |
(let ((when (nth 1 form))) |
|---|
| 468 |
(if (or (memq 'eval when) (memq :execute when)) |
|---|
| 469 |
(list* 'eval-when (cons 'compile when) (cddr form)) |
|---|
| 470 |
form))) |
|---|
| 471 |
(t (eval form) form))) |
|---|
| 472 |
|
|---|
| 473 |
(defmacro load-time-value (form &optional read-only) |
|---|
| 474 |
"Like `progn', but evaluates the body at load time. |
|---|
| 475 |
The result of the body appears to the compiler as a quoted constant." |
|---|
| 476 |
(if (cl-compiling-file) |
|---|
| 477 |
(let* ((temp (gentemp "--cl-load-time--")) |
|---|
| 478 |
(set (list 'set (list 'quote temp) form))) |
|---|
| 479 |
(if (and (fboundp 'byte-compile-file-form-defmumble) |
|---|
| 480 |
(boundp 'this-kind) (boundp 'that-one)) |
|---|
| 481 |
(fset 'byte-compile-file-form |
|---|
| 482 |
(list 'lambda '(form) |
|---|
| 483 |
(list 'fset '(quote byte-compile-file-form) |
|---|
| 484 |
(list 'quote |
|---|
| 485 |
(symbol-function 'byte-compile-file-form))) |
|---|
| 486 |
(list 'byte-compile-file-form (list 'quote set)) |
|---|
| 487 |
'(byte-compile-file-form form))) |
|---|
| 488 |
(print set (symbol-value 'outbuffer))) |
|---|
| 489 |
(list 'symbol-value (list 'quote temp))) |
|---|
| 490 |
(list 'quote (eval form)))) |
|---|
| 491 |
|
|---|
| 492 |
|
|---|
| 493 |
|
|---|
| 494 |
|
|---|
| 495 |
(defmacro case (expr &rest clauses) |
|---|
| 496 |
"Eval EXPR and choose among clauses on that value. |
|---|
| 497 |
Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared |
|---|
| 498 |
against each key in each KEYLIST; the corresponding BODY is evaluated. |
|---|
| 499 |
If no clause succeeds, case returns nil. A single atom may be used in |
|---|
| 500 |
place of a KEYLIST of one atom. A KEYLIST of t or `otherwise' is |
|---|
| 501 |
allowed only in the final clause, and matches if no other keys match. |
|---|
| 502 |
Key values are compared by `eql'. |
|---|
| 503 |
\n(fn EXPR (KEYLIST BODY...)...)" |
|---|
| 504 |
(let* ((temp (if (cl-simple-expr-p expr 3) expr (make-symbol "--cl-var--"))) |
|---|
| 505 |
(head-list nil) |
|---|
| 506 |
(body (cons |
|---|
| 507 |
'cond |
|---|
| 508 |
(mapcar |
|---|
| 509 |
(function |
|---|
| 510 |
(lambda (c) |
|---|
| 511 |
(cons (cond ((memq (car c) '(t otherwise)) t) |
|---|
| 512 |
((eq (car c) 'ecase-error-flag) |
|---|
| 513 |
(list 'error "ecase failed: %s, %s" |
|---|
| 514 |
temp (list 'quote (reverse head-list)))) |
|---|
| 515 |
((listp (car c)) |
|---|
| 516 |
(setq head-list (append (car c) head-list)) |
|---|
| 517 |
(list 'member* temp (list 'quote (car c)))) |
|---|
| 518 |
(t |
|---|
| 519 |
(if (memq (car c) head-list) |
|---|
| 520 |
(error "Duplicate key in case: %s" |
|---|
| 521 |
(car c))) |
|---|
| 522 |
(push (car c) head-list) |
|---|
| 523 |
(list 'eql temp (list 'quote (car c))))) |
|---|
| 524 |
(or (cdr c) '(nil))))) |
|---|
| 525 |
clauses)))) |
|---|
| 526 |
(if (eq temp expr) body |
|---|
| 527 |
(list 'let (list (list temp expr)) body)))) |
|---|
| 528 |
|
|---|
| 529 |
(defmacro ecase (expr &rest clauses) |
|---|
| 530 |
"Like `case', but error if no case fits. |
|---|
| 531 |
`otherwise'-clauses are not allowed. |
|---|
| 532 |
\n(fn EXPR (KEYLIST BODY...)...)" |
|---|
| 533 |
(list* 'case expr (append clauses '((ecase-error-flag))))) |
|---|
| 534 |
|
|---|
| 535 |
(defmacro typecase (expr &rest clauses) |
|---|
| 536 |
"Evals EXPR, chooses among clauses on that value. |
|---|
| 537 |
Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it |
|---|
| 538 |
satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, |
|---|
| 539 |
typecase returns nil. A TYPE of t or `otherwise' is allowed only in the |
|---|
| 540 |
final clause, and matches if no other keys match. |
|---|
| 541 |
\n(fn EXPR (TYPE BODY...)...)" |
|---|
| 542 |
(let* ((temp (if (cl-simple-expr-p expr 3) expr (make-symbol "--cl-var--"))) |
|---|
| 543 |
(type-list nil) |
|---|
| 544 |
(body (cons |
|---|
| 545 |
'cond |
|---|
| 546 |
(mapcar |
|---|
| 547 |
(function |
|---|
| 548 |
(lambda (c) |
|---|
| 549 |
(cons (cond ((eq (car c) 'otherwise) t) |
|---|
| 550 |
((eq (car c) 'ecase-error-flag) |
|---|
| 551 |
(list 'error "etypecase failed: %s, %s" |
|---|
| 552 |
temp (list 'quote (reverse type-list)))) |
|---|
| 553 |
(t |
|---|
| 554 |
(push (car c) type-list) |
|---|
| 555 |
(cl-make-type-test temp (car c)))) |
|---|
| 556 |
(or (cdr c) '(nil))))) |
|---|
| 557 |
clauses)))) |
|---|
| 558 |
(if (eq temp expr) body |
|---|
| 559 |
(list 'let (list (list temp expr)) body)))) |
|---|
| 560 |
|
|---|
| 561 |
(defmacro etypecase (expr &rest clauses) |
|---|
| 562 |
"Like `typecase', but error if no case fits. |
|---|
| 563 |
`otherwise'-clauses are not allowed. |
|---|
| 564 |
\n(fn EXPR (TYPE BODY...)...)" |
|---|
| 565 |
(list* 'typecase expr (append clauses '((ecase-error-flag))))) |
|---|
| 566 |
|
|---|
| 567 |
|
|---|
| 568 |
|
|---|
| 569 |
|
|---|
| 570 |
(defmacro block (name &rest body) |
|---|
| 571 |
"Define a lexically-scoped block named NAME. |
|---|
| 572 |
NAME may be any symbol. Code inside the BODY forms can call `return-from' |
|---|
| 573 |
to jump prematurely out of the block. This differs from `catch' and `throw' |
|---|
| 574 |
in two respects: First, the NAME is an unevaluated symbol rather than a |
|---|
| 575 |
quoted symbol or other form; and second, NAME is lexically rather than |
|---|
| 576 |
dynamically scoped: Only references to it within BODY will work. These |
|---|
| 577 |
references may appear inside macro expansions, but not inside functions |
|---|
| 578 |
called from BODY." |
|---|
| 579 |
(if (cl-safe-expr-p (cons 'progn body)) (cons 'progn body) |
|---|
| 580 |
(list 'cl-block-wrapper |
|---|
| 581 |
(list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) |
|---|
| 582 |
body)))) |
|---|
| 583 |
|
|---|
| 584 |
(defvar cl-active-block-names nil) |
|---|
| 585 |
|
|---|
| 586 |
(put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block) |
|---|
| 587 |
(defun cl-byte-compile-block (cl-form) |
|---|
| 588 |
(if (fboundp 'byte-compile-form-do-effect) |
|---|
| 589 |
(progn |
|---|
| 590 |
(let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) |
|---|
| 591 |
(cl-active-block-names (cons cl-entry cl-active-block-names)) |
|---|
| 592 |
(cl-body (byte-compile-top-level |
|---|
| 593 |
(cons 'progn (cddr (nth 1 cl-form)))))) |
|---|
| 594 |
(if (cdr cl-entry) |
|---|
| 595 |
(byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body)) |
|---|
| 596 |
(byte-compile-form cl-body)))) |
|---|
| 597 |
(byte-compile-form (nth 1 cl-form)))) |
|---|
| 598 |
|
|---|
| 599 |
(put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw) |
|---|
| 600 |
(defun cl-byte-compile-throw (cl-form) |
|---|
| 601 |
(let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) |
|---|
| 602 |
(if cl-found (setcdr cl-found t))) |
|---|
| 603 |
(byte-compile-normal-call (cons 'throw (cdr cl-form)))) |
|---|
| 604 |
|
|---|
| 605 |
(defmacro return (&optional result) |
|---|
| 606 |
"Return from the block named nil. |
|---|
| 607 |
This is equivalent to `(return-from nil RESULT)'." |
|---|
| 608 |
(list 'return-from nil result)) |
|---|
| 609 |
|
|---|
| 610 |
(defmacro return-from (name &optional result) |
|---|
| 611 |
"Return from the block named NAME. |
|---|
| 612 |
This jump out to the innermost enclosing `(block NAME ...)' form, |
|---|
| 613 |
returning RESULT from that form (or nil if RESULT is omitted). |
|---|
| 614 |
This is compatible with Common Lisp, but note that `defun' and |
|---|
| 615 |
`defmacro' do not create implicit blocks as they do in Common Lisp." |
|---|
| 616 |
(let ((name2 (intern (format "--cl-block-%s--" name)))) |
|---|
| 617 |
(list 'cl-block-throw (list 'quote name2) result))) |
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
(defvar args) (defvar loop-accum-var) (defvar loop-accum-vars) |
|---|
| 623 |
(defvar loop-bindings) (defvar loop-body) (defvar loop-destr-temps) |
|---|
| 624 |
(defvar loop-finally) (defvar loop-finish-flag) (defvar loop-first-flag) |
|---|
| 625 |
(defvar loop-initially) (defvar loop-map-form) (defvar loop-name) |
|---|
| 626 |
(defvar loop-result) (defvar loop-result-explicit) |
|---|
| 627 |
(defvar loop-result-var) (defvar loop-steps) (defvar loop-symbol-macs) |
|---|
| 628 |
|
|---|
| 629 |
(defmacro loop (&rest args) |
|---|
| 630 |
"The Common Lisp `loop' macro. |
|---|
| 631 |
Valid clauses are: |
|---|
| 632 |
for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM, |
|---|
| 633 |
for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR, |
|---|
| 634 |
for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND, |
|---|
| 635 |
always COND, never COND, thereis COND, collect EXPR into VAR, |
|---|
| 636 |
append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR, |
|---|
| 637 |
count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR, |
|---|
| 638 |
if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], |
|---|
| 639 |
unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...], |
|---|
| 640 |
do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR, |
|---|
| 641 |
finally return EXPR, named NAME. |
|---|
| 642 |
|
|---|
| 643 |
\(fn CLAUSE...)" |
|---|
| 644 |
(if (not (memq t (mapcar 'symbolp (delq nil (delq t (copy-list args)))))) |
|---|
| 645 |
(list 'block nil (list* 'while t args)) |
|---|
| 646 |
(let ((loop-name nil) (loop-bindings nil) |
|---|
| 647 |
(loop-body nil) (loop-steps nil) |
|---|
| 648 |
(loop-result nil) (loop-result-explicit nil) |
|---|
| 649 |
(loop-result-var nil) (loop-finish-flag nil) |
|---|
| 650 |
(loop-accum-var nil) (loop-accum-vars nil) |
|---|
| 651 |
(loop-initially nil) (loop-finally nil) |
|---|
| 652 |
(loop-map-form nil) (loop-first-flag nil) |
|---|
| 653 |
(loop-destr-temps nil) (loop-symbol-macs nil)) |
|---|
| 654 |
(setq args (append args '(cl-end-loop))) |
|---|
| 655 |
(while (not (eq (car args) 'cl-end-loop)) (cl-parse-loop-clause)) |
|---|
| 656 |
(if loop-finish-flag |
|---|
| 657 |
(push `((,loop-finish-flag t)) loop-bindings)) |
|---|
| 658 |
(if loop-first-flag |
|---|
| 659 |
(progn (push `((,loop-first-flag t)) loop-bindings) |
|---|
| 660 |
(push `(setq ,loop-first-flag nil) loop-steps))) |
|---|
| 661 |
(let* ((epilogue (nconc (nreverse loop-finally) |
|---|
| 662 |
(list (or loop-result-explicit loop-result)))) |
|---|
| 663 |
(ands (cl-loop-build-ands (nreverse loop-body))) |
|---|
| 664 |
(while-body (nconc (cadr ands) (nreverse loop-steps))) |
|---|
| 665 |
(body (append |
|---|
| 666 |
(nreverse loop-initially) |
|---|
| 667 |
(list (if loop-map-form |
|---|
| 668 |
(list 'block '--cl-finish-- |
|---|
| 669 |
(subst |
|---|
| 670 |
(if (eq (car ands) t) while-body |
|---|
| 671 |
(cons `(or ,(car ands) |
|---|
| 672 |
(return-from --cl-finish-- |
|---|
| 673 |
nil)) |
|---|
| 674 |
while-body)) |
|---|
| 675 |
'--cl-map loop-map-form)) |
|---|
| 676 |
(list* 'while (car ands) while-body))) |
|---|
| 677 |
(if loop-finish-flag |
|---|
| 678 |
(if (equal epilogue '(nil)) (list loop-result-var) |
|---|
| 679 |
`((if ,loop-finish-flag |
|---|
| 680 |
(progn ,@epilogue) ,loop-result-var))) |
|---|
| 681 |
epilogue)))) |
|---|
| 682 |
(if loop-result-var (push (list loop-result-var) loop-bindings)) |
|---|
| 683 |
(while loop-bindings |
|---|
| 684 |
(if (cdar loop-bindings) |
|---|
| 685 |
(setq body (list (cl-loop-let (pop loop-bindings) body t))) |
|---|
| 686 |
(let ((lets nil)) |
|---|
| 687 |
(while (and loop-bindings |
|---|
| 688 |
(not (cdar loop-bindings))) |
|---|
| 689 |
(push (car (pop loop-bindings)) lets)) |
|---|
| 690 |
(setq body (list (cl-loop-let lets body nil)))))) |
|---|
| 691 |
(if loop-symbol-macs |
|---|
| 692 |
(setq body (list (list* 'symbol-macrolet loop-symbol-macs body)))) |
|---|
| 693 |
(list* 'block loop-name body))))) |
|---|
| 694 |
|
|---|
| 695 |
(defun cl-parse-loop-clause () |
|---|
| 696 |
(let ((word (pop args)) |
|---|
| 697 |
(hash-types '(hash-key hash-keys hash-value hash-values)) |
|---|
| 698 |
(key-types '(key-code key-codes key-seq key-seqs |
|---|
| 699 |
key-binding key-bindings))) |
|---|
| 700 |
(cond |
|---|
| 701 |
|
|---|
| 702 |
((null args) |
|---|
| 703 |
(error "Malformed `loop' macro")) |
|---|
| 704 |
|
|---|
| 705 |
((eq word 'named) |
|---|
| 706 |
(setq loop-name (pop args))) |
|---|
| 707 |
|
|---|
| 708 |
((eq word 'initially) |
|---|
| 709 |
(if (memq (car args) '(do doing)) (pop args)) |
|---|
| 710 |
(or (consp (car args)) (error "Syntax error on `initially' clause")) |
|---|
| 711 |
(while (consp (car args)) |
|---|
| 712 |
(push (pop args) loop-initially))) |
|---|
| 713 |
|
|---|
| 714 |
((eq word 'finally) |
|---|
| 715 |
(if (eq (car args) 'return) |
|---|
| 716 |
(setq loop-result-explicit (or (cl-pop2 args) '(quote nil))) |
|---|
| 717 |
(if (memq (car args) '(do doing)) (pop args)) |
|---|
| 718 |
(or (consp (car args)) (error "Syntax error on `finally' clause")) |
|---|
| 719 |
(if (and (eq (caar args) 'return) (null loop-name)) |
|---|
| 720 |
(setq loop-result-explicit (or (nth 1 (pop args)) '(quote nil))) |
|---|
| 721 |
(while (consp (car args)) |
|---|
| 722 |
(push (pop args) loop-finally))))) |
|---|
| 723 |
|
|---|
| 724 |
((memq word '(for as)) |
|---|
| 725 |
(let ((loop-for-bindings nil) (loop-for-sets nil) (loop-for-steps nil) |
|---|
| 726 |
(ands nil)) |
|---|
| 727 |
(while |
|---|
| 728 |
|
|---|
| 729 |
|
|---|
| 730 |
|
|---|
| 731 |
(let ((var (or (pop args) (gensym "--cl-var--")))) |
|---|
| 732 |
(setq word (pop args)) |
|---|
| 733 |
(if (eq word 'being) (setq word (pop args))) |
|---|
| 734 |
(if (memq word '(the each)) (setq word (pop args))) |
|---|
| 735 |
(if (memq word '(buffer buffers)) |
|---|
| 736 |
(setq word 'in args (cons '(buffer-list) args))) |
|---|
| 737 |
(cond |
|---|
| 738 |
|
|---|
| 739 |
((memq word '(from downfrom upfrom to downto upto |
|---|
| 740 |
above below by)) |
|---|
| 741 |
(push word args) |
|---|
| 742 |
(if (memq (car args) '(downto above)) |
|---|
| 743 |
(error "Must specify `from' value for downward loop")) |
|---|
| 744 |
(let* ((down (or (eq (car args) 'downfrom) |
|---|
| 745 |
(memq (caddr args) '(downto above)))) |
|---|
| 746 |
(excl (or (memq (car args) '(above below)) |
|---|
| 747 |
(memq (caddr args) '(above below)))) |
|---|
| 748 |
(start (and (memq (car args) '(from upfrom downfrom)) |
|---|
| 749 |
(cl-pop2 args))) |
|---|
| 750 |
(end (and (memq (car args) |
|---|
| 751 |
'(to upto downto above below)) |
|---|
| 752 |
(cl-pop2 args))) |
|---|
| 753 |
(step (and (eq (car args) 'by) (cl-pop2 args))) |
|---|
| 754 |
(end-var (and (not (cl-const-expr-p end)) |
|---|
| 755 |
(make-symbol "--cl-var--"))) |
|---|
| 756 |
(step-var (and (not (cl-const-expr-p step)) |
|---|
|
|---|