diff options
| author | Stefan Monnier | 2015-01-26 11:43:06 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2015-01-26 11:43:06 -0500 |
| commit | a9a3d429e6e53e2be0b20e84f9809dba1d03e52d (patch) | |
| tree | 7a524468a14403d10d8a2eace08b803110447b7a | |
| parent | 4cdde9196fb4fafb00b0c51b908fd605274147bd (diff) | |
| download | emacs-a9a3d429e6e53e2be0b20e84f9809dba1d03e52d.tar.gz emacs-a9a3d429e6e53e2be0b20e84f9809dba1d03e52d.zip | |
* lisp/emacs-lisp/cl-generic.el (cl--generic-method): New struct.
(cl--generic): The method-table is now a (list-of cl--generic-method).
(cl--generic-member-method): New function.
(cl-generic-define-method): Use it.
(cl--generic-build-combined-method, cl--generic-cache-miss):
Adapt to new method-table.
(cl--generic-no-next-method-function): Add `method' argument.
(cl-generic-call-method): Adapt to new method representation.
(cl--generic-cnm-sample, cl--generic-nnm-sample): Adjust.
(cl-find-method, cl-method-qualifiers): New functions.
(cl--generic-method-info): Adapt to new method representation.
Return a string for the qualifiers.
(cl--generic-describe):
* lisp/emacs-lisp/eieio-opt.el (eieio-help-class): Adjust accordingly.
(eieio-all-generic-functions, eieio-method-documentation):
Adjust to new method representation.
* lisp/emacs-lisp/eieio-compat.el (eieio--defmethod): Use cl-find-method.
* test/automated/cl-generic-tests.el: Try and make sure cl-lib is not
required at run-time.
| -rw-r--r-- | lisp/ChangeLog | 22 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-generic.el | 158 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-compat.el | 9 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-opt.el | 18 | ||||
| -rw-r--r-- | test/ChangeLog | 5 | ||||
| -rw-r--r-- | test/automated/cl-generic-tests.el | 4 |
6 files changed, 133 insertions, 83 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 0bdf4e275fa..ff352a25eea 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,27 @@ | |||
| 1 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | |||
| 4 | * emacs-lisp/cl-generic.el (cl--generic-method): New struct. | ||
| 5 | (cl--generic): The method-table is now a (list-of cl--generic-method). | ||
| 6 | (cl--generic-member-method): New function. | ||
| 7 | (cl-generic-define-method): Use it. | ||
| 8 | (cl--generic-build-combined-method, cl--generic-cache-miss): | ||
| 9 | Adapt to new method-table. | ||
| 10 | (cl--generic-no-next-method-function): Add `method' argument. | ||
| 11 | (cl-generic-call-method): Adapt to new method representation. | ||
| 12 | (cl--generic-cnm-sample, cl--generic-nnm-sample): Adjust. | ||
| 13 | (cl-find-method, cl-method-qualifiers): New functions. | ||
| 14 | (cl--generic-method-info): Adapt to new method representation. | ||
| 15 | Return a string for the qualifiers. | ||
| 16 | (cl--generic-describe): | ||
| 17 | * emacs-lisp/eieio-opt.el (eieio-help-class): Adjust accordingly. | ||
| 18 | (eieio-all-generic-functions, eieio-method-documentation): | ||
| 19 | Adjust to new method representation. | ||
| 20 | |||
| 21 | * emacs-lisp/eieio-compat.el (eieio--defmethod): Use cl-find-method. | ||
| 22 | |||
| 23 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 24 | |||
| 3 | * emacs-lisp/cl-generic.el: Add a method-combination hook. | 25 | * emacs-lisp/cl-generic.el: Add a method-combination hook. |
| 4 | (cl-generic-method-combination-function): New var. | 26 | (cl-generic-method-combination-function): New var. |
| 5 | (cl--generic-lambda): Remove `with-cnm' arg. | 27 | (cl--generic-lambda): Remove `with-cnm' arg. |
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 4245959c8a4..1bb70963a57 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el | |||
| @@ -33,10 +33,6 @@ | |||
| 33 | ;; code generation. Given how rarely method-combinations are used, | 33 | ;; code generation. Given how rarely method-combinations are used, |
| 34 | ;; I just provided a cl-generic-method-combination-function, which | 34 | ;; I just provided a cl-generic-method-combination-function, which |
| 35 | ;; people can use if they are really desperate for such functionality. | 35 | ;; people can use if they are really desperate for such functionality. |
| 36 | ;; - Method and generic function objects: CLOS defines methods as objects | ||
| 37 | ;; (same for generic functions), whereas we don't offer such an abstraction. | ||
| 38 | ;; - `no-next-method' should receive the "calling method" object, but since we | ||
| 39 | ;; don't have such a thing, we pass nil instead. | ||
| 40 | ;; - In defgeneric we don't support the options: | 36 | ;; - In defgeneric we don't support the options: |
| 41 | ;; declare, :method-combination, :generic-function-class, :method-class, | 37 | ;; declare, :method-combination, :generic-function-class, :method-class, |
| 42 | ;; :method. | 38 | ;; :method. |
| @@ -50,6 +46,8 @@ | |||
| 50 | ;; eieio-core adds dispatch on: | 46 | ;; eieio-core adds dispatch on: |
| 51 | ;; - class of eieio objects | 47 | ;; - class of eieio objects |
| 52 | ;; - actual class argument, using the syntax (subclass <class>). | 48 | ;; - actual class argument, using the syntax (subclass <class>). |
| 49 | ;; - cl-generic-method-combination-function (i.s.o define-method-combination). | ||
| 50 | ;; - cl-generic-call-method (which replaces make-method and call-method). | ||
| 53 | 51 | ||
| 54 | ;; Efficiency considerations: overall, I've made an effort to make this fairly | 52 | ;; Efficiency considerations: overall, I've made an effort to make this fairly |
| 55 | ;; efficient for the expected case (e.g. no constant redefinition of methods). | 53 | ;; efficient for the expected case (e.g. no constant redefinition of methods). |
| @@ -103,6 +101,18 @@ that for all other (PRIORITY . TAGCODE) where PRIORITY ≤ N, then | |||
| 103 | "Function to get the list of types that a given \"tag\" matches. | 101 | "Function to get the list of types that a given \"tag\" matches. |
| 104 | They should be sorted from most specific to least specific.") | 102 | They should be sorted from most specific to least specific.") |
| 105 | 103 | ||
| 104 | (cl-defstruct (cl--generic-method | ||
| 105 | (:constructor nil) | ||
| 106 | (:constructor cl--generic-method-make | ||
| 107 | (specializers qualifiers uses-cnm function)) | ||
| 108 | (:predicate nil)) | ||
| 109 | (specializers nil :read-only t :type list) | ||
| 110 | (qualifiers nil :read-only t :type (list-of atom)) | ||
| 111 | ;; USES-CNM is a boolean indicating if FUNCTION expects an extra argument | ||
| 112 | ;; holding the next-method. | ||
| 113 | (uses-cnm nil :read-only t :type boolean) | ||
| 114 | (function nil :read-only t :type function)) | ||
| 115 | |||
| 106 | (cl-defstruct (cl--generic | 116 | (cl-defstruct (cl--generic |
| 107 | (:constructor nil) | 117 | (:constructor nil) |
| 108 | (:constructor cl--generic-make | 118 | (:constructor cl--generic-make |
| @@ -116,12 +126,7 @@ They should be sorted from most specific to least specific.") | |||
| 116 | ;; decide in which order to sort them. | 126 | ;; decide in which order to sort them. |
| 117 | ;; The most important dispatch is last in the list (and the least is first). | 127 | ;; The most important dispatch is last in the list (and the least is first). |
| 118 | (dispatches nil :type (list-of (cons natnum (list-of tagcode)))) | 128 | (dispatches nil :type (list-of (cons natnum (list-of tagcode)))) |
| 119 | ;; `method-table' is a list of | 129 | (method-table nil :type (list-of cl--generic-method))) |
| 120 | ;; ((SPECIALIZERS . QUALIFIERS) USES-CNM . FUNCTION), where | ||
| 121 | ;; USES-CNM is a boolean indicating if FUNCTION calls `cl-call-next-method' | ||
| 122 | ;; (and hence expects an extra argument holding the next-method). | ||
| 123 | (method-table nil :type (list-of (cons (cons (list-of type) (list-of atom)) | ||
| 124 | (cons boolean function))))) | ||
| 125 | 130 | ||
| 126 | (defmacro cl--generic (name) | 131 | (defmacro cl--generic (name) |
| 127 | `(get ,name 'cl--generic)) | 132 | `(get ,name 'cl--generic)) |
| @@ -344,15 +349,25 @@ which case this method will be invoked when the argument is `eql' to VAL. | |||
| 344 | (cl-generic-define-method ',name ',qualifiers ',args | 349 | (cl-generic-define-method ',name ',qualifiers ',args |
| 345 | ,uses-cnm ,fun))))) | 350 | ,uses-cnm ,fun))))) |
| 346 | 351 | ||
| 352 | (defun cl--generic-member-method (specializers qualifiers methods) | ||
| 353 | (while | ||
| 354 | (and methods | ||
| 355 | (let ((m (car methods))) | ||
| 356 | (not (and (equal (cl--generic-method-specializers m) specializers) | ||
| 357 | (equal (cl--generic-method-qualifiers m) qualifiers))))) | ||
| 358 | (setq methods (cdr methods)) | ||
| 359 | methods)) | ||
| 360 | |||
| 347 | ;;;###autoload | 361 | ;;;###autoload |
| 348 | (defun cl-generic-define-method (name qualifiers args uses-cnm function) | 362 | (defun cl-generic-define-method (name qualifiers args uses-cnm function) |
| 349 | (let* ((generic (cl-generic-ensure-function name)) | 363 | (let* ((generic (cl-generic-ensure-function name)) |
| 350 | (mandatory (cl--generic-mandatory-args args)) | 364 | (mandatory (cl--generic-mandatory-args args)) |
| 351 | (specializers | 365 | (specializers |
| 352 | (mapcar (lambda (arg) (if (consp arg) (cadr arg) t)) mandatory)) | 366 | (mapcar (lambda (arg) (if (consp arg) (cadr arg) t)) mandatory)) |
| 353 | (key (cons specializers qualifiers)) | 367 | (method (cl--generic-method-make |
| 368 | specializers qualifiers uses-cnm function)) | ||
| 354 | (mt (cl--generic-method-table generic)) | 369 | (mt (cl--generic-method-table generic)) |
| 355 | (me (assoc key mt)) | 370 | (me (cl--generic-member-method specializers qualifiers mt)) |
| 356 | (dispatches (cl--generic-dispatches generic)) | 371 | (dispatches (cl--generic-dispatches generic)) |
| 357 | (i 0)) | 372 | (i 0)) |
| 358 | (dolist (specializer specializers) | 373 | (dolist (specializer specializers) |
| @@ -367,9 +382,8 @@ which case this method will be invoked when the argument is `eql' to VAL. | |||
| 367 | (nreverse (sort (cons tagcode (cdr x)) | 382 | (nreverse (sort (cons tagcode (cdr x)) |
| 368 | #'car-less-than-car)))) | 383 | #'car-less-than-car)))) |
| 369 | (setq i (1+ i)))) | 384 | (setq i (1+ i)))) |
| 370 | (if me (setcdr me (cons uses-cnm function)) | 385 | (if me (setcar me method) |
| 371 | (setf (cl--generic-method-table generic) | 386 | (setf (cl--generic-method-table generic) (cons method mt))) |
| 372 | (cons `(,key ,uses-cnm . ,function) mt))) | ||
| 373 | (cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) . ,specializers)) | 387 | (cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) . ,specializers)) |
| 374 | current-load-list :test #'equal) | 388 | current-load-list :test #'equal) |
| 375 | (let ((gfun (cl--generic-make-function generic)) | 389 | (let ((gfun (cl--generic-make-function generic)) |
| @@ -459,47 +473,40 @@ for all those different tags in the method-cache.") | |||
| 459 | (gethash (cons generic-name methods) | 473 | (gethash (cons generic-name methods) |
| 460 | cl--generic-combined-method-memoization) | 474 | cl--generic-combined-method-memoization) |
| 461 | (let ((mets-by-qual ())) | 475 | (let ((mets-by-qual ())) |
| 462 | (dolist (qm methods) | 476 | (dolist (method methods) |
| 463 | (let* ((qualifiers (cdar qm)) | 477 | (let* ((qualifiers (cl--generic-method-qualifiers method)) |
| 464 | (x (assoc qualifiers mets-by-qual))) | 478 | (x (assoc qualifiers mets-by-qual))) |
| 465 | ;; FIXME: sadly, alist-get only uses `assq' and we need `assoc'. | 479 | ;; FIXME: sadly, alist-get only uses `assq' and we need `assoc'. |
| 466 | ;;(push (cdr qm) (alist-get qualifiers mets-by-qual))) | 480 | ;;(push (cdr qm) (alist-get qualifiers mets-by-qual))) |
| 467 | (if x | 481 | (if x |
| 468 | (push (cdr qm) (cdr x)) | 482 | (push method (cdr x)) |
| 469 | (push (list qualifiers (cdr qm)) mets-by-qual)))) | 483 | (push (list qualifiers method) mets-by-qual)))) |
| 470 | (funcall cl-generic-method-combination-function | 484 | (funcall cl-generic-method-combination-function |
| 471 | generic-name mets-by-qual)))) | 485 | generic-name mets-by-qual)))) |
| 472 | 486 | ||
| 473 | (defun cl--generic-no-next-method-function (generic) | 487 | (defun cl--generic-no-next-method-function (generic method) |
| 474 | (lambda (&rest args) | 488 | (lambda (&rest args) |
| 475 | ;; FIXME: CLOS passes as second arg the "calling method". | 489 | (apply #'cl-no-next-method generic method args))) |
| 476 | ;; We don't currently have "method objects" like CLOS | ||
| 477 | ;; does so we can't really do it the CLOS way. | ||
| 478 | ;; The closest would be to pass the lambda corresponding | ||
| 479 | ;; to the method, or maybe the ((SPECIALIZERS | ||
| 480 | ;; . QUALIFIER) USE-CNM . FUNCTION) entry from the method | ||
| 481 | ;; table, but the caller wouldn't be able to do much with | ||
| 482 | ;; it anyway. So we pass nil for now. | ||
| 483 | (apply #'cl-no-next-method generic nil args))) | ||
| 484 | 490 | ||
| 485 | (defun cl-generic-call-method (generic-name method &optional fun) | 491 | (defun cl-generic-call-method (generic-name method &optional fun) |
| 486 | "Return a function that calls METHOD. | 492 | "Return a function that calls METHOD. |
| 487 | FUN is the function that should be called when METHOD calls | 493 | FUN is the function that should be called when METHOD calls |
| 488 | `call-next-method'." | 494 | `call-next-method'." |
| 489 | (pcase method | 495 | (if (not (cl--generic-method-uses-cnm method)) |
| 490 | (`(nil . ,method) method) | 496 | (cl--generic-method-function method) |
| 491 | (`(,_uses-cnm . ,method) | 497 | (let ((met-fun (cl--generic-method-function method)) |
| 492 | (let ((next (or fun (cl--generic-no-next-method-function generic-name)))) | 498 | (next (or fun (cl--generic-no-next-method-function |
| 493 | (lambda (&rest args) | 499 | generic-name method)))) |
| 494 | (apply method | 500 | (lambda (&rest args) |
| 495 | ;; FIXME: This sucks: passing just `next' would | 501 | (apply met-fun |
| 496 | ;; be a lot more efficient than the lambda+apply | 502 | ;; FIXME: This sucks: passing just `next' would |
| 497 | ;; quasi-η, but we need this to implement the | 503 | ;; be a lot more efficient than the lambda+apply |
| 498 | ;; "if call-next-method is called with no | 504 | ;; quasi-η, but we need this to implement the |
| 499 | ;; arguments, then use the previous arguments". | 505 | ;; "if call-next-method is called with no |
| 500 | (lambda (&rest cnm-args) | 506 | ;; arguments, then use the previous arguments". |
| 501 | (apply next (or cnm-args args))) | 507 | (lambda (&rest cnm-args) |
| 502 | args)))))) | 508 | (apply next (or cnm-args args))) |
| 509 | args))))) | ||
| 503 | 510 | ||
| 504 | (defun cl--generic-standard-method-combination (generic-name mets-by-qual) | 511 | (defun cl--generic-standard-method-combination (generic-name mets-by-qual) |
| 505 | (dolist (x mets-by-qual) | 512 | (dolist (x mets-by-qual) |
| @@ -533,10 +540,10 @@ FUN is the function that should be called when METHOD calls | |||
| 533 | (setq fun (cl-generic-call-method generic-name method fun))) | 540 | (setq fun (cl-generic-call-method generic-name method fun))) |
| 534 | fun)))) | 541 | fun)))) |
| 535 | 542 | ||
| 536 | (defconst cl--generic-nnm-sample (cl--generic-no-next-method-function 'dummy)) | 543 | (defconst cl--generic-nnm-sample (cl--generic-no-next-method-function t t)) |
| 537 | (defconst cl--generic-cnm-sample | 544 | (defconst cl--generic-cnm-sample |
| 538 | (funcall (cl--generic-build-combined-method | 545 | (funcall (cl--generic-build-combined-method |
| 539 | nil `(((specializer . nil) t . ,#'identity))))) | 546 | nil (list (cl--generic-method-make () () t #'identity))))) |
| 540 | 547 | ||
| 541 | (defun cl--generic-isnot-nnm-p (cnm) | 548 | (defun cl--generic-isnot-nnm-p (cnm) |
| 542 | "Return non-nil if CNM is the function that calls `cl-no-next-method'." | 549 | "Return non-nil if CNM is the function that calls `cl-no-next-method'." |
| @@ -567,11 +574,13 @@ FUN is the function that should be called when METHOD calls | |||
| 567 | (defun cl--generic-cache-miss (generic dispatch-arg dispatches-left tags) | 574 | (defun cl--generic-cache-miss (generic dispatch-arg dispatches-left tags) |
| 568 | (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags))) | 575 | (let ((types (apply #'append (mapcar cl-generic-tag-types-function tags))) |
| 569 | (methods '())) | 576 | (methods '())) |
| 570 | (dolist (method-desc (cl--generic-method-table generic)) | 577 | (dolist (method (cl--generic-method-table generic)) |
| 571 | (let* ((specializer (or (nth dispatch-arg (caar method-desc)) t)) | 578 | (let* ((specializer (or (nth dispatch-arg |
| 579 | (cl--generic-method-specializers method)) | ||
| 580 | t)) | ||
| 572 | (m (member specializer types))) | 581 | (m (member specializer types))) |
| 573 | (when m | 582 | (when m |
| 574 | (push (cons (length m) method-desc) methods)))) | 583 | (push (cons (length m) method) methods)))) |
| 575 | ;; Sort the methods, most specific first. | 584 | ;; Sort the methods, most specific first. |
| 576 | ;; It would be tempting to sort them once and for all in the method-table | 585 | ;; It would be tempting to sort them once and for all in the method-table |
| 577 | ;; rather than here, but the order might depend on the actual argument | 586 | ;; rather than here, but the order might depend on the actual argument |
| @@ -614,6 +623,14 @@ Can only be used from within the lexical body of a primary or around method." | |||
| 614 | (declare (obsolete "make sure there's always a next method, or catch `cl-no-next-method' instead" "25.1")) | 623 | (declare (obsolete "make sure there's always a next method, or catch `cl-no-next-method' instead" "25.1")) |
| 615 | (error "cl-next-method-p only allowed inside primary and around methods")) | 624 | (error "cl-next-method-p only allowed inside primary and around methods")) |
| 616 | 625 | ||
| 626 | ;;;###autoload | ||
| 627 | (defun cl-find-method (generic qualifiers specializers) | ||
| 628 | (car (cl--generic-member-method | ||
| 629 | specializers qualifiers | ||
| 630 | (cl--generic-method-table (cl--generic generic))))) | ||
| 631 | |||
| 632 | (defalias 'cl-method-qualifiers 'cl--generic-method-qualifiers) | ||
| 633 | |||
| 617 | ;;; Add support for describe-function | 634 | ;;; Add support for describe-function |
| 618 | 635 | ||
| 619 | (defun cl--generic-search-method (met-name) | 636 | (defun cl--generic-search-method (met-name) |
| @@ -638,22 +655,30 @@ Can only be used from within the lexical body of a primary or around method." | |||
| 638 | `(cl-defmethod . ,#'cl--generic-search-method))) | 655 | `(cl-defmethod . ,#'cl--generic-search-method))) |
| 639 | 656 | ||
| 640 | (defun cl--generic-method-info (method) | 657 | (defun cl--generic-method-info (method) |
| 641 | (pcase-let ((`((,specializers . ,qualifier) ,uses-cnm . ,function) method)) | 658 | (let* ((specializers (cl--generic-method-specializers method)) |
| 642 | (let* ((args (help-function-arglist function 'names)) | 659 | (qualifiers (cl--generic-method-qualifiers method)) |
| 643 | (docstring (documentation function)) | 660 | (uses-cnm (cl--generic-method-uses-cnm method)) |
| 644 | (doconly (if docstring | 661 | (function (cl--generic-method-function method)) |
| 645 | (let ((split (help-split-fundoc docstring nil))) | 662 | (args (help-function-arglist function 'names)) |
| 646 | (if split (cdr split) docstring)))) | 663 | (docstring (documentation function)) |
| 647 | (combined-args ())) | 664 | (qual-string |
| 648 | (if uses-cnm (setq args (cdr args))) | 665 | (if (null qualifiers) "" |
| 649 | (dolist (specializer specializers) | 666 | (cl-assert (consp qualifiers)) |
| 650 | (let ((arg (if (eq '&rest (car args)) | 667 | (let ((s (prin1-to-string qualifiers))) |
| 651 | (intern (format "arg%d" (length combined-args))) | 668 | (concat (substring s 1 -1) " ")))) |
| 652 | (pop args)))) | 669 | (doconly (if docstring |
| 653 | (push (if (eq specializer t) arg (list arg specializer)) | 670 | (let ((split (help-split-fundoc docstring nil))) |
| 654 | combined-args))) | 671 | (if split (cdr split) docstring)))) |
| 655 | (setq combined-args (append (nreverse combined-args) args)) | 672 | (combined-args ())) |
| 656 | (list qualifier combined-args doconly)))) | 673 | (if uses-cnm (setq args (cdr args))) |
| 674 | (dolist (specializer specializers) | ||
| 675 | (let ((arg (if (eq '&rest (car args)) | ||
| 676 | (intern (format "arg%d" (length combined-args))) | ||
| 677 | (pop args)))) | ||
| 678 | (push (if (eq specializer t) arg (list arg specializer)) | ||
| 679 | combined-args))) | ||
| 680 | (setq combined-args (append (nreverse combined-args) args)) | ||
| 681 | (list qual-string combined-args doconly))) | ||
| 657 | 682 | ||
| 658 | (add-hook 'help-fns-describe-function-functions #'cl--generic-describe) | 683 | (add-hook 'help-fns-describe-function-functions #'cl--generic-describe) |
| 659 | (defun cl--generic-describe (function) | 684 | (defun cl--generic-describe (function) |
| @@ -667,8 +692,9 @@ Can only be used from within the lexical body of a primary or around method." | |||
| 667 | (dolist (method (cl--generic-method-table generic)) | 692 | (dolist (method (cl--generic-method-table generic)) |
| 668 | (let* ((info (cl--generic-method-info method))) | 693 | (let* ((info (cl--generic-method-info method))) |
| 669 | ;; FIXME: Add hyperlinks for the types as well. | 694 | ;; FIXME: Add hyperlinks for the types as well. |
| 670 | (insert (format "%S %S" (nth 0 info) (nth 1 info))) | 695 | (insert (format "%s%S" (nth 0 info) (nth 1 info))) |
| 671 | (let* ((met-name (cons function (caar method))) | 696 | (let* ((met-name (cons function |
| 697 | (cl--generic-method-specializers method))) | ||
| 672 | (file (find-lisp-object-file-name met-name 'cl-defmethod))) | 698 | (file (find-lisp-object-file-name met-name 'cl-defmethod))) |
| 673 | (when file | 699 | (when file |
| 674 | (insert " in `") | 700 | (insert " in `") |
diff --git a/lisp/emacs-lisp/eieio-compat.el b/lisp/emacs-lisp/eieio-compat.el index 30bb5cee994..fcca99d79d5 100644 --- a/lisp/emacs-lisp/eieio-compat.el +++ b/lisp/emacs-lisp/eieio-compat.el | |||
| @@ -203,11 +203,10 @@ Summary: | |||
| 203 | ;; or :after, make sure there's a matching dummy primary. | 203 | ;; or :after, make sure there's a matching dummy primary. |
| 204 | (when (and (memq kind '(:before :after)) | 204 | (when (and (memq kind '(:before :after)) |
| 205 | ;; FIXME: Use `cl-find-method'? | 205 | ;; FIXME: Use `cl-find-method'? |
| 206 | (not (assoc (cons (mapcar (lambda (arg) | 206 | (not (cl-find-method method () |
| 207 | (if (consp arg) (nth 1 arg) t)) | 207 | (mapcar (lambda (arg) |
| 208 | specializers) | 208 | (if (consp arg) (nth 1 arg) t)) |
| 209 | nil) | 209 | specializers)))) |
| 210 | (cl--generic-method-table (cl--generic method))))) | ||
| 211 | (cl-generic-define-method method () specializers t | 210 | (cl-generic-define-method method () specializers t |
| 212 | (lambda (cnm &rest args) | 211 | (lambda (cnm &rest args) |
| 213 | (if (cl--generic-isnot-nnm-p cnm) | 212 | (if (cl--generic-isnot-nnm-p cnm) |
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el index a131b02ee16..8d40edf5624 100644 --- a/lisp/emacs-lisp/eieio-opt.el +++ b/lisp/emacs-lisp/eieio-opt.el | |||
| @@ -129,9 +129,9 @@ If CLASS is actually an object, then also display current values of that object. | |||
| 129 | (insert "`") | 129 | (insert "`") |
| 130 | (help-insert-xref-button (symbol-name generic) 'help-function generic) | 130 | (help-insert-xref-button (symbol-name generic) 'help-function generic) |
| 131 | (insert "'") | 131 | (insert "'") |
| 132 | (pcase-dolist (`(,qualifier ,args ,doc) | 132 | (pcase-dolist (`(,qualifiers ,args ,doc) |
| 133 | (eieio-method-documentation generic class)) | 133 | (eieio-method-documentation generic class)) |
| 134 | (insert (format " %S %S\n" qualifier args) | 134 | (insert (format " %s%S\n" qualifiers args) |
| 135 | (or doc ""))) | 135 | (or doc ""))) |
| 136 | (insert "\n\n"))))) | 136 | (insert "\n\n"))))) |
| 137 | 137 | ||
| @@ -325,10 +325,9 @@ methods for CLASS." | |||
| 325 | (and generic | 325 | (and generic |
| 326 | (catch 'found | 326 | (catch 'found |
| 327 | (if (null class) (throw 'found t)) | 327 | (if (null class) (throw 'found t)) |
| 328 | (pcase-dolist (`((,specializers . ,_qualifier) . ,_) | 328 | (dolist (method (cl--generic-method-table generic)) |
| 329 | (cl--generic-method-table generic)) | ||
| 330 | (if (eieio--specializers-apply-to-class-p | 329 | (if (eieio--specializers-apply-to-class-p |
| 331 | specializers class) | 330 | (cl--generic-method-specializers method) class) |
| 332 | (throw 'found t)))) | 331 | (throw 'found t)))) |
| 333 | (push symbol l))))) | 332 | (push symbol l))))) |
| 334 | l)) | 333 | l)) |
| @@ -336,15 +335,14 @@ methods for CLASS." | |||
| 336 | (defun eieio-method-documentation (generic class) | 335 | (defun eieio-method-documentation (generic class) |
| 337 | "Return info for all methods of GENERIC applicable to CLASS. | 336 | "Return info for all methods of GENERIC applicable to CLASS. |
| 338 | The value returned is a list of elements of the form | 337 | The value returned is a list of elements of the form |
| 339 | \(QUALIFIER ARGS DOC)." | 338 | \(QUALIFIERS ARGS DOC)." |
| 340 | (let ((generic (cl--generic generic)) | 339 | (let ((generic (cl--generic generic)) |
| 341 | (docs ())) | 340 | (docs ())) |
| 342 | (when generic | 341 | (when generic |
| 343 | (dolist (method (cl--generic-method-table generic)) | 342 | (dolist (method (cl--generic-method-table generic)) |
| 344 | (pcase-let ((`((,specializers . ,_qualifier) . ,_) method)) | 343 | (when (eieio--specializers-apply-to-class-p |
| 345 | (when (eieio--specializers-apply-to-class-p | 344 | (cl--generic-method-specializers method) class) |
| 346 | specializers class) | 345 | (push (cl--generic-method-info method) docs)))) |
| 347 | (push (cl--generic-method-info method) docs))))) | ||
| 348 | docs)) | 346 | docs)) |
| 349 | 347 | ||
| 350 | ;;; METHOD STATS | 348 | ;;; METHOD STATS |
diff --git a/test/ChangeLog b/test/ChangeLog index 9a31da45416..61ab8b6595a 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,5 +1,10 @@ | |||
| 1 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * automated/cl-generic-tests.el: Try and make sure cl-lib is not | ||
| 4 | required at run-time. | ||
| 5 | |||
| 6 | 2015-01-26 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 7 | |||
| 3 | * automated/cl-generic-tests.el (cl-generic-test-11-next-method-p): | 8 | * automated/cl-generic-tests.el (cl-generic-test-11-next-method-p): |
| 4 | New test. | 9 | New test. |
| 5 | 10 | ||
diff --git a/test/automated/cl-generic-tests.el b/test/automated/cl-generic-tests.el index 5b3a9fdc2a1..5194802fa00 100644 --- a/test/automated/cl-generic-tests.el +++ b/test/automated/cl-generic-tests.el | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | ;;; Code: | 24 | ;;; Code: |
| 25 | 25 | ||
| 26 | (require 'ert) | 26 | (eval-when-compile (require 'ert)) ;Don't indirectly require cl-lib at run-time. |
| 27 | (require 'cl-lib) | 27 | (require 'cl-generic) |
| 28 | 28 | ||
| 29 | (cl-defgeneric cl--generic-1 (x y)) | 29 | (cl-defgeneric cl--generic-1 (x y)) |
| 30 | (cl-defgeneric (setf cl--generic-1) (v y z) "My generic doc.") | 30 | (cl-defgeneric (setf cl--generic-1) (v y z) "My generic doc.") |