aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/ChangeLog7
-rw-r--r--lisp/emacs-lisp/cl-generic.el1
-rw-r--r--lisp/emacs-lisp/cl-macs.el148
-rw-r--r--test/automated/cl-lib-tests.el17
4 files changed, 124 insertions, 49 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e9e910a8857..41898bee686 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,12 @@
12015-03-16 Stefan Monnier <monnier@iro.umontreal.ca> 12015-03-16 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * emacs-lisp/cl-macs.el (cl--transform-lambda): Rework to avoid
4 cl--do-arglist in more cases; add comments to explain what's going on.
5 (cl--do-&aux): New function extracted from cl--do-arglist.
6 (cl--do-arglist): Use it.
7
8 * emacs-lisp/cl-generic.el: Add Version: header, for ELPA purposes.
9
3 * obsolete/iswitchb.el (iswitchb-read-buffer): Add `predicate' arg. 10 * obsolete/iswitchb.el (iswitchb-read-buffer): Add `predicate' arg.
4 * isearchb.el (isearchb-iswitchb): Adjust accordingly. 11 * isearchb.el (isearchb-iswitchb): Adjust accordingly.
5 * ido.el (ido-read-buffer): Add `predicate' argument. 12 * ido.el (ido-read-buffer): Add `predicate' argument.
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index a8483ea1355..41c760e960e 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -3,6 +3,7 @@
3;; Copyright (C) 2015 Free Software Foundation, Inc. 3;; Copyright (C) 2015 Free Software Foundation, Inc.
4 4
5;; Author: Stefan Monnier <monnier@iro.umontreal.ca> 5;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
6;; Version: 1.0
6 7
7;; This file is part of GNU Emacs. 8;; This file is part of GNU Emacs.
8 9
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 36f263cd20a..712a7485167 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -220,7 +220,20 @@ The name is made by appending a number to PREFIX, default \"G\"."
220(defconst cl--lambda-list-keywords 220(defconst cl--lambda-list-keywords
221 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) 221 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
222 222
223(defvar cl--bind-block) (defvar cl--bind-defs) (defvar cl--bind-enquote) 223;; Internal hacks used in formal arg lists:
224;; - &cl-quote: Added to formal-arglists to mean that any default value
225;; mentioned in the formal arglist should be considered as implicitly
226;; quoted rather than evaluated. This is used in `cl-defsubst' when
227;; performing compiler-macro-expansion, since at that time the
228;; arguments hold expressions rather than values.
229;; - &cl-defs (DEF . DEFS): Gives the default value to use for missing
230;; optional arguments which don't have an explicit default value.
231;; DEFS is an alist mapping vars to their default default value.
232;; and DEF is the default default to use for all other vars.
233
234(defvar cl--bind-block) ;Name of surrounding block, only use for `signal' data.
235(defvar cl--bind-defs) ;(DEF . DEFS) giving the "default default" for optargs.
236(defvar cl--bind-enquote) ;Non-nil if &cl-quote was in the formal arglist!
224(defvar cl--bind-lets) (defvar cl--bind-forms) 237(defvar cl--bind-lets) (defvar cl--bind-forms)
225 238
226(defun cl--transform-lambda (form bind-block) 239(defun cl--transform-lambda (form bind-block)
@@ -229,19 +242,26 @@ BIND-BLOCK is the name of the symbol to which the function will be bound,
229and which will be used for the name of the `cl-block' surrounding the 242and which will be used for the name of the `cl-block' surrounding the
230function's body. 243function's body.
231FORM is of the form (ARGS . BODY)." 244FORM is of the form (ARGS . BODY)."
232 ;; FIXME: (lambda (a &aux b) 1) expands to (lambda (a &rest --cl-rest--) ...)
233 ;; where the --cl-rest-- is clearly undesired.
234 (let* ((args (car form)) (body (cdr form)) (orig-args args) 245 (let* ((args (car form)) (body (cdr form)) (orig-args args)
235 (cl--bind-block bind-block) (cl--bind-defs nil) (cl--bind-enquote nil) 246 (cl--bind-block bind-block) (cl--bind-defs nil) (cl--bind-enquote nil)
236 (cl--bind-lets nil) (cl--bind-forms nil)
237 (parsed-body (macroexp-parse-body body)) 247 (parsed-body (macroexp-parse-body body))
238 (header (car parsed-body)) (simple-args nil)) 248 (header (car parsed-body)) (simple-args nil))
239 (setq body (cdr parsed-body)) 249 (setq body (cdr parsed-body))
250 ;; "(. X) to (&rest X)" conversion already done in cl--do-arglist, but we
251 ;; do it here as well, so as to be able to see if we can avoid
252 ;; cl--do-arglist.
240 (setq args (if (listp args) (cl-copy-list args) (list '&rest args))) 253 (setq args (if (listp args) (cl-copy-list args) (list '&rest args)))
241 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) 254 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
242 (if (setq cl--bind-defs (cadr (memq '&cl-defs args))) 255 (let ((cl-defs (memq '&cl-defs args)))
243 (setq args (delq '&cl-defs (delq cl--bind-defs args)) 256 (when cl-defs
244 cl--bind-defs (cadr cl--bind-defs))) 257 (setq cl--bind-defs (cadr cl-defs))
258 ;; Remove "&cl-defs DEFS" from args.
259 (setcdr cl-defs (cddr cl-defs))
260 (setq args (delq '&cl-defs args))
261 ;; Optimize away trivial &cl-defs.
262 (if (and (null (car cl--bind-defs))
263 (cl-every (lambda (x) (null (cadr x))) (cdr cl--bind-defs)))
264 (setq cl--bind-defs nil))))
245 (if (setq cl--bind-enquote (memq '&cl-quote args)) 265 (if (setq cl--bind-enquote (memq '&cl-quote args))
246 (setq args (delq '&cl-quote args))) 266 (setq args (delq '&cl-quote args)))
247 (if (memq '&whole args) (error "&whole not currently implemented")) 267 (if (memq '&whole args) (error "&whole not currently implemented"))
@@ -249,6 +269,9 @@ FORM is of the form (ARGS . BODY)."
249 (v (cadr p))) 269 (v (cadr p)))
250 (if p (setq args (nconc (delq (car p) (delq v args)) 270 (if p (setq args (nconc (delq (car p) (delq v args))
251 `(&aux (,v macroexpand-all-environment)))))) 271 `(&aux (,v macroexpand-all-environment))))))
272 ;; Take away all the simple args whose parsing can be handled more
273 ;; efficiently by a plain old `lambda' than the manual parsing generated
274 ;; by `cl--do-arglist'.
252 (while (and args (symbolp (car args)) 275 (while (and args (symbolp (car args))
253 (not (memq (car args) '(nil &rest &body &key &aux))) 276 (not (memq (car args) '(nil &rest &body &key &aux)))
254 (not (and (eq (car args) '&optional) 277 (not (and (eq (car args) '&optional)
@@ -256,30 +279,50 @@ FORM is of the form (ARGS . BODY)."
256 (push (pop args) simple-args)) 279 (push (pop args) simple-args))
257 (or (eq cl--bind-block 'cl-none) 280 (or (eq cl--bind-block 'cl-none)
258 (setq body (list `(cl-block ,cl--bind-block ,@body)))) 281 (setq body (list `(cl-block ,cl--bind-block ,@body))))
259 (if (null args) 282 (let* ((cl--bind-lets nil) (cl--bind-forms nil)
260 (cl-list* nil (nreverse simple-args) (nconc header body)) 283 (rest-args
261 (if (memq '&optional simple-args) (push '&optional args)) 284 (cond
262 (cl--do-arglist args nil (- (length simple-args) 285 ((null args) nil)
263 (if (memq '&optional simple-args) 1 0))) 286 ((eq (car args) '&aux)
264 (setq cl--bind-lets (nreverse cl--bind-lets)) 287 (cl--do-&aux args)
265 (cl-list* nil 288 (setq cl--bind-lets (nreverse cl--bind-lets))
266 (nconc (nreverse simple-args) 289 nil)
267 (list '&rest (car (pop cl--bind-lets)))) 290 (t ;; `simple-args' doesn't handle all the parsing that we need,
268 (nconc (save-match-data ;; Macro expansion can take place in the 291 ;; so we pass the rest to cl--do-arglist which will do
269 ;; middle of apparently harmless computation, so it 292 ;; "manual" parsing.
270 ;; should not touch the match-data. 293 (let ((slen (length simple-args)))
271 (require 'help-fns) 294 (when (memq '&optional simple-args)
272 (cons (help-add-fundoc-usage 295 (push '&optional args) (cl-decf slen))
273 (if (stringp (car header)) (pop header)) 296 (setq header
274 ;; Be careful with make-symbol and (back)quote, 297 ;; Macro expansion can take place in the middle of
275 ;; see bug#12884. 298 ;; apparently harmless computation, so it should not
276 (let ((print-gensym nil) (print-quoted t)) 299 ;; touch the match-data.
277 (format "%S" (cons 'fn (cl--make-usage-args 300 (save-match-data
278 orig-args))))) 301 (require 'help-fns)
279 header)) 302 (cons (help-add-fundoc-usage
280 (list `(let* ,cl--bind-lets 303 (if (stringp (car header)) (pop header))
281 ,@(nreverse cl--bind-forms) 304 ;; Be careful with make-symbol and (back)quote,
282 ,@body))))))) 305 ;; see bug#12884.
306 (let ((print-gensym nil) (print-quoted t))
307 (format "%S" (cons 'fn (cl--make-usage-args
308 orig-args)))))
309 header)))
310 ;; FIXME: we'd want to choose an arg name for the &rest param
311 ;; and pass that as `expr' to cl--do-arglist, but that ends up
312 ;; generating code with a redundant let-binding, so we instead
313 ;; pass a dummy and then look in cl--bind-lets to find what var
314 ;; this was bound to.
315 (cl--do-arglist args :dummy slen)
316 (setq cl--bind-lets (nreverse cl--bind-lets))
317 ;; (cl-assert (eq :dummy (nth 1 (car cl--bind-lets))))
318 (list '&rest (car (pop cl--bind-lets))))))))
319 `(nil
320 (,@(nreverse simple-args) ,@rest-args)
321 ,@header
322 ,(macroexp-let* cl--bind-lets
323 (macroexp-progn
324 `(,@(nreverse cl--bind-forms)
325 ,@body)))))))
283 326
284;;;###autoload 327;;;###autoload
285(defmacro cl-defun (name args &rest body) 328(defmacro cl-defun (name args &rest body)
@@ -422,8 +465,7 @@ its argument list allows full Common Lisp conventions."
422 (setcdr last nil) 465 (setcdr last nil)
423 (nconc (cl--make-usage-args arglist) (cl--make-usage-var tail))) 466 (nconc (cl--make-usage-args arglist) (cl--make-usage-var tail)))
424 (setcdr last tail))) 467 (setcdr last tail)))
425 ;; `orig-args' can contain &cl-defs (an internal 468 ;; `orig-args' can contain &cl-defs.
426 ;; CL thingy I don't understand), so remove it.
427 (let ((x (memq '&cl-defs arglist))) 469 (let ((x (memq '&cl-defs arglist)))
428 (when x (setq arglist (delq (car x) (remq (cadr x) arglist))))) 470 (when x (setq arglist (delq (car x) (remq (cadr x) arglist)))))
429 (let ((state nil)) 471 (let ((state nil))
@@ -450,6 +492,17 @@ its argument list allows full Common Lisp conventions."
450 )))) 492 ))))
451 arglist)))) 493 arglist))))
452 494
495(defun cl--do-&aux (args)
496 (while (and (eq (car args) '&aux) (pop args))
497 (while (and args (not (memq (car args) cl--lambda-list-keywords)))
498 (if (consp (car args))
499 (if (and cl--bind-enquote (cl-cadar args))
500 (cl--do-arglist (caar args)
501 `',(cadr (pop args)))
502 (cl--do-arglist (caar args) (cadr (pop args))))
503 (cl--do-arglist (pop args) nil))))
504 (if args (error "Malformed argument list ends with: %S" args)))
505
453(defun cl--do-arglist (args expr &optional num) ; uses cl--bind-* 506(defun cl--do-arglist (args expr &optional num) ; uses cl--bind-*
454 (if (nlistp args) 507 (if (nlistp args)
455 (if (or (memq args cl--lambda-list-keywords) (not (symbolp args))) 508 (if (or (memq args cl--lambda-list-keywords) (not (symbolp args)))
@@ -459,8 +512,7 @@ its argument list allows full Common Lisp conventions."
459 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) 512 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p)))))
460 (let ((p (memq '&body args))) (if p (setcar p '&rest))) 513 (let ((p (memq '&body args))) (if p (setcar p '&rest)))
461 (if (memq '&environment args) (error "&environment used incorrectly")) 514 (if (memq '&environment args) (error "&environment used incorrectly"))
462 (let ((save-args args) 515 (let ((restarg (memq '&rest args))
463 (restarg (memq '&rest args))
464 (safety (if (cl--compiling-file) cl--optimize-safety 3)) 516 (safety (if (cl--compiling-file) cl--optimize-safety 3))
465 (keys nil) 517 (keys nil)
466 (laterarg nil) (exactarg nil) minarg) 518 (laterarg nil) (exactarg nil) minarg)
@@ -530,7 +582,12 @@ its argument list allows full Common Lisp conventions."
530 (intern (format ":%s" name))))) 582 (intern (format ":%s" name)))))
531 (varg (if (consp (car arg)) (cl-cadar arg) (car arg))) 583 (varg (if (consp (car arg)) (cl-cadar arg) (car arg)))
532 (def (if (cdr arg) (cadr arg) 584 (def (if (cdr arg) (cadr arg)
533 (or (car cl--bind-defs) (cadr (assq varg cl--bind-defs))))) 585 ;; The ordering between those two or clauses is
586 ;; irrelevant, since in practice only one of the two
587 ;; is ever non-nil (the car is only used for
588 ;; cl-deftype which doesn't use the cdr).
589 (or (car cl--bind-defs)
590 (cadr (assq varg cl--bind-defs)))))
534 (look `(plist-member ,restarg ',karg))) 591 (look `(plist-member ,restarg ',karg)))
535 (and def cl--bind-enquote (setq def `',def)) 592 (and def cl--bind-enquote (setq def `',def))
536 (if (cddr arg) 593 (if (cddr arg)
@@ -567,15 +624,8 @@ its argument list allows full Common Lisp conventions."
567 keys) 624 keys)
568 (car ,var))))))) 625 (car ,var)))))))
569 (push `(let ((,var ,restarg)) ,check) cl--bind-forms))) 626 (push `(let ((,var ,restarg)) ,check) cl--bind-forms)))
570 (while (and (eq (car args) '&aux) (pop args)) 627 (cl--do-&aux args)
571 (while (and args (not (memq (car args) cl--lambda-list-keywords))) 628 nil)))
572 (if (consp (car args))
573 (if (and cl--bind-enquote (cl-cadar args))
574 (cl--do-arglist (caar args)
575 `',(cadr (pop args)))
576 (cl--do-arglist (caar args) (cadr (pop args))))
577 (cl--do-arglist (pop args) nil))))
578 (if args (error "Malformed argument list %s" save-args)))))
579 629
580(defun cl--arglist-args (args) 630(defun cl--arglist-args (args)
581 (if (nlistp args) (list args) 631 (if (nlistp args) (list args)
@@ -2608,7 +2658,7 @@ non-nil value, that slot cannot be set via `setf'.
2608 (make (cl-mapcar (function (lambda (s d) (if (memq s anames) s d))) 2658 (make (cl-mapcar (function (lambda (s d) (if (memq s anames) s d)))
2609 slots defaults))) 2659 slots defaults)))
2610 (push `(cl-defsubst ,name 2660 (push `(cl-defsubst ,name
2611 (&cl-defs '(nil ,@descs) ,@args) 2661 (&cl-defs (nil ,@descs) ,@args)
2612 ,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs))) 2662 ,@(if (cl--safe-expr-p `(progn ,@(mapcar #'cl-second descs)))
2613 '((declare (side-effect-free t)))) 2663 '((declare (side-effect-free t))))
2614 (,(or type #'vector) ,@make)) 2664 (,(or type #'vector) ,@make))
@@ -2716,8 +2766,8 @@ Of course, we really can't know that for sure, so it's just a heuristic."
2716 (t 2766 (t
2717 (inline-quote (or (cl-typep ,val ',head) 2767 (inline-quote (or (cl-typep ,val ',head)
2718 (cl-typep ,val ',rest))))))))) 2768 (cl-typep ,val ',rest)))))))))
2719 (`(member . ,args) 2769 (`(eql ,v) (inline-quote (and (eql ,val ',v) t)))
2720 (inline-quote (and (memql ,val ',args) t))) 2770 (`(member . ,args) (inline-quote (and (memql ,val ',args) t)))
2721 (`(satisfies ,pred) (inline-quote (funcall #',pred ,val))) 2771 (`(satisfies ,pred) (inline-quote (funcall #',pred ,val)))
2722 ((and (pred symbolp) type (guard (get type 'cl-deftype-handler))) 2772 ((and (pred symbolp) type (guard (get type 'cl-deftype-handler)))
2723 (inline-quote 2773 (inline-quote
@@ -2977,7 +3027,7 @@ The type name can then be used in `cl-typecase', `cl-check-type', etc."
2977 (declare (debug cl-defmacro) (doc-string 3) (indent 2)) 3027 (declare (debug cl-defmacro) (doc-string 3) (indent 2))
2978 `(cl-eval-when (compile load eval) 3028 `(cl-eval-when (compile load eval)
2979 (put ',name 'cl-deftype-handler 3029 (put ',name 'cl-deftype-handler
2980 (cl-function (lambda (&cl-defs '('*) ,@arglist) ,@body))))) 3030 (cl-function (lambda (&cl-defs ('*) ,@arglist) ,@body)))))
2981 3031
2982(cl-deftype extended-char () `(and character (not base-char))) 3032(cl-deftype extended-char () `(and character (not base-char)))
2983 3033
diff --git a/test/automated/cl-lib-tests.el b/test/automated/cl-lib-tests.el
index 1c36e7d7abf..2c188a40059 100644
--- a/test/automated/cl-lib-tests.el
+++ b/test/automated/cl-lib-tests.el
@@ -427,4 +427,21 @@
427(ert-deftest cl-flet-test () 427(ert-deftest cl-flet-test ()
428 (should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5))) 428 (should (equal (cl-flet ((f1 (x) x)) (let ((x #'f1)) (funcall x 5))) 5)))
429 429
430(ert-deftest cl-lib-test-typep ()
431 (cl-deftype cl-lib-test-type (&optional x) `(member ,x))
432 ;; Make sure we correctly implement the rule that deftype's optional args
433 ;; default to `*' rather than to nil.
434 (should (cl-typep '* 'cl-lib-test-type))
435 (should-not (cl-typep 1 'cl-lib-test-type)))
436
437(ert-deftest cl-lib-arglist-performance ()
438 ;; An `&aux' should not cause lambda's arglist to be turned into an &rest
439 ;; that's parsed by hand.
440 (should (eq () (nth 1 (nth 1 (macroexpand
441 '(cl-function (lambda (&aux (x 1)) x)))))))
442 (cl-defstruct (cl-lib--s (:constructor cl-lib--s-make (&optional a))) a)
443 ;; Similarly the &cl-defs thingy shouldn't cause fallback to manual parsing
444 ;; of args if the default for optional args is nil.
445 (should (equal '(&optional a) (help-function-arglist 'cl-lib--s-make))))
446
430;;; cl-lib.el ends here 447;;; cl-lib.el ends here