aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier2015-05-21 23:46:10 -0400
committerStefan Monnier2015-05-21 23:46:10 -0400
commitea92591983a05bd85d52a6a07dd3b7149feb46d2 (patch)
treeb22c6fde14f284e276e587198740d621aaced913 /lisp
parentf590fc2760f8b8180a4caf77cea81840e37fe29e (diff)
downloademacs-ea92591983a05bd85d52a6a07dd3b7149feb46d2.tar.gz
emacs-ea92591983a05bd85d52a6a07dd3b7149feb46d2.zip
Change defgeneric so it doesn't completely redefine the function
* lisp/emacs-lisp/cl-generic.el (cl-generic-define): Don't throw away previously defined methods. (cl-generic-define-method): Let-bind purify-flag instead of using `fset'. (cl--generic-prefill-dispatchers): Only define during compilation. (cl-method-qualifiers): Remove redundant alias. (help-fns-short-filename): Silence byte-compiler. * test/automated/cl-generic-tests.el: Adjust to new defgeneric semantics.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog.163
-rw-r--r--lisp/emacs-lisp/cl-generic.el43
2 files changed, 27 insertions, 19 deletions
diff --git a/lisp/ChangeLog.16 b/lisp/ChangeLog.16
index 457c1511af8..bc5267aadba 100644
--- a/lisp/ChangeLog.16
+++ b/lisp/ChangeLog.16
@@ -5030,8 +5030,7 @@
5030 * mouse.el (mouse-yank-primarY): Look for frame-type w32, not 5030 * mouse.el (mouse-yank-primarY): Look for frame-type w32, not
5031 system-type windows-nt. 5031 system-type windows-nt.
5032 5032
5033 * server.el (server-create-window-system-frame): Look for window 5033 * server.el (server-create-window-system-frame): Look for window type.
5034 type.
5035 (server-proces-filter): Only force a window system when windows-nt 5034 (server-proces-filter): Only force a window system when windows-nt
5036 _and_ w32. Explain why. 5035 _and_ w32. Explain why.
5037 5036
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index 13585bcaf18..b3c127f48f7 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -237,14 +237,19 @@ BODY, if present, is used as the body of a default method.
237 (`(,spec-args . ,_) (cl--generic-split-args args)) 237 (`(,spec-args . ,_) (cl--generic-split-args args))
238 (mandatory (mapcar #'car spec-args)) 238 (mandatory (mapcar #'car spec-args))
239 (apo (assq :argument-precedence-order options))) 239 (apo (assq :argument-precedence-order options)))
240 (setf (cl--generic-dispatches generic) nil) 240 (unless (fboundp name)
241 ;; If the generic function was fmakunbound, throw away previous methods.
242 (setf (cl--generic-dispatches generic) nil)
243 (setf (cl--generic-method-table generic) nil))
241 (when apo 244 (when apo
242 (dolist (arg (cdr apo)) 245 (dolist (arg (cdr apo))
243 (let ((pos (memq arg mandatory))) 246 (let ((pos (memq arg mandatory)))
244 (unless pos (error "%S is not a mandatory argument" arg)) 247 (unless pos (error "%S is not a mandatory argument" arg))
245 (push (list (- (length mandatory) (length pos))) 248 (let* ((argno (- (length mandatory) (length pos)))
246 (cl--generic-dispatches generic))))) 249 (dispatches (cl--generic-dispatches generic))
247 (setf (cl--generic-method-table generic) nil) 250 (dispatch (or (assq argno dispatches) (list argno))))
251 (setf (cl--generic-dispatches generic)
252 (cons dispatch (delq dispatch dispatches)))))))
248 (setf (cl--generic-options generic) options) 253 (setf (cl--generic-options generic) options)
249 (cl--generic-make-function generic))) 254 (cl--generic-make-function generic)))
250 255
@@ -438,16 +443,14 @@ which case this method will be invoked when the argument is `eql' to VAL.
438 ;; the generic function. 443 ;; the generic function.
439 current-load-list) 444 current-load-list)
440 ;; For aliases, cl--generic-name gives us the actual name. 445 ;; For aliases, cl--generic-name gives us the actual name.
441 (funcall 446 (let ((purify-flag
442 (if purify-flag 447 ;; BEWARE! Don't purify this function definition, since that leads
443 ;; BEWARE! Don't purify this function definition, since that leads 448 ;; to memory corruption if the hash-tables it holds are modified
444 ;; to memory corruption if the hash-tables it holds are modified 449 ;; (the GC doesn't trace those pointers).
445 ;; (the GC doesn't trace those pointers). 450 nil))
446 #'fset 451 ;; But do use `defalias', so that it interacts properly with nadvice,
447 ;; But do use `defalias' in the normal case, so that it interacts 452 ;; e.g. for tracing/debug-on-entry.
448 ;; properly with nadvice, e.g. for tracing/debug-on-entry. 453 (defalias (cl--generic-name generic) gfun)))))
449 #'defalias)
450 (cl--generic-name generic) gfun))))
451 454
452(defmacro cl--generic-with-memoization (place &rest code) 455(defmacro cl--generic-with-memoization (place &rest code)
453 (declare (indent 1) (debug t)) 456 (declare (indent 1) (debug t))
@@ -705,6 +708,11 @@ methods.")
705 (if (eq specializer t) (list cl--generic-t-generalizer) 708 (if (eq specializer t) (list cl--generic-t-generalizer)
706 (error "Unknown specializer %S" specializer))) 709 (error "Unknown specializer %S" specializer)))
707 710
711(eval-when-compile
712 ;; This macro is brittle and only really important in order to be
713 ;; able to preload cl-generic without also preloading the byte-compiler,
714 ;; So we use `eval-when-compile' so as not keep it available longer than
715 ;; strictly needed.
708(defmacro cl--generic-prefill-dispatchers (arg-or-context specializer) 716(defmacro cl--generic-prefill-dispatchers (arg-or-context specializer)
709 (unless (integerp arg-or-context) 717 (unless (integerp arg-or-context)
710 (setq arg-or-context `(&context . ,arg-or-context))) 718 (setq arg-or-context `(&context . ,arg-or-context)))
@@ -722,7 +730,7 @@ methods.")
722 ,@(cl-generic-generalizers ',specializer) 730 ,@(cl-generic-generalizers ',specializer)
723 ,cl--generic-t-generalizer))) 731 ,cl--generic-t-generalizer)))
724 ;; (message "Prefilling for %S with \n%S" dispatch ',fun) 732 ;; (message "Prefilling for %S with \n%S" dispatch ',fun)
725 (puthash dispatch ',fun cl--generic-dispatchers)))) 733 (puthash dispatch ',fun cl--generic-dispatchers)))))
726 734
727(cl-defmethod cl-generic-combine-methods (generic methods) 735(cl-defmethod cl-generic-combine-methods (generic methods)
728 "Standard support for :after, :before, :around, and `:extra NAME' qualifiers." 736 "Standard support for :after, :before, :around, and `:extra NAME' qualifiers."
@@ -796,8 +804,6 @@ Can only be used from within the lexical body of a primary or around method."
796 specializers qualifiers 804 specializers qualifiers
797 (cl--generic-method-table (cl--generic generic))))) 805 (cl--generic-method-table (cl--generic generic)))))
798 806
799(defalias 'cl-method-qualifiers 'cl--generic-method-qualifiers)
800
801;;; Add support for describe-function 807;;; Add support for describe-function
802 808
803(defun cl--generic-search-method (met-name) 809(defun cl--generic-search-method (met-name)
@@ -850,6 +856,9 @@ Can only be used from within the lexical body of a primary or around method."
850 856
851(add-hook 'help-fns-describe-function-functions #'cl--generic-describe) 857(add-hook 'help-fns-describe-function-functions #'cl--generic-describe)
852(defun cl--generic-describe (function) 858(defun cl--generic-describe (function)
859 ;; Supposedly this is called from help-fns, so help-fns should be loaded at
860 ;; this point.
861 (declare-function help-fns-short-filename "help-fns" (filename))
853 (let ((generic (if (symbolp function) (cl--generic function)))) 862 (let ((generic (if (symbolp function) (cl--generic function))))
854 (when generic 863 (when generic
855 (require 'help-mode) ;Needed for `help-function-def' button! 864 (require 'help-mode) ;Needed for `help-function-def' button!