aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/emacs-lisp/cl-generic.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/cl-generic.el')
-rw-r--r--lisp/emacs-lisp/cl-generic.el71
1 files changed, 51 insertions, 20 deletions
diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el
index c64376b940f..1a3f8e1f4d5 100644
--- a/lisp/emacs-lisp/cl-generic.el
+++ b/lisp/emacs-lisp/cl-generic.el
@@ -166,6 +166,10 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value TAG
166(defmacro cl--generic (name) 166(defmacro cl--generic (name)
167 `(get ,name 'cl--generic)) 167 `(get ,name 'cl--generic))
168 168
169(defun cl-generic-p (f)
170 "Return non-nil if F is a generic function."
171 (and (symbolp f) (cl--generic f)))
172
169(defun cl-generic-ensure-function (name &optional noerror) 173(defun cl-generic-ensure-function (name &optional noerror)
170 (let (generic 174 (let (generic
171 (origname name)) 175 (origname name))
@@ -182,8 +186,7 @@ SPECIALIZERS-FUNCTION takes as first argument a tag value TAG
182 origname)) 186 origname))
183 (if generic 187 (if generic
184 (cl-assert (eq name (cl--generic-name generic))) 188 (cl-assert (eq name (cl--generic-name generic)))
185 (setf (cl--generic name) (setq generic (cl--generic-make name))) 189 (setf (cl--generic name) (setq generic (cl--generic-make name))))
186 (defalias name (cl--generic-make-function generic)))
187 generic)) 190 generic))
188 191
189;;;###autoload 192;;;###autoload
@@ -410,7 +413,7 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
410\(and can be extended) by the various methods of `cl-generic-generalizers'. 413\(and can be extended) by the various methods of `cl-generic-generalizers'.
411 414
412\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" 415\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
413 (declare (doc-string 3) (indent 2) 416 (declare (doc-string 3) (indent defun)
414 (debug 417 (debug
415 (&define ; this means we are defining something 418 (&define ; this means we are defining something
416 [&or name ("setf" name :name setf)] 419 [&or name ("setf" name :name setf)]
@@ -501,25 +504,26 @@ The set of acceptable TYPEs (also called \"specializers\") is defined
501 (cons method mt) 504 (cons method mt)
502 ;; Keep the ordering; important for methods with :extra qualifiers. 505 ;; Keep the ordering; important for methods with :extra qualifiers.
503 (mapcar (lambda (x) (if (eq x (car me)) method x)) mt))) 506 (mapcar (lambda (x) (if (eq x (car me)) method x)) mt)))
504 (cl-pushnew `(cl-defmethod . ,(cl--generic-load-hist-format 507 (let ((sym (cl--generic-name generic))) ; Actual name (for aliases).
505 (cl--generic-name generic) 508 (unless (symbol-function sym)
506 qualifiers specializers)) 509 (defalias sym 'dummy)) ;Record definition into load-history.
507 current-load-list :test #'equal) 510 (cl-pushnew `(cl-defmethod . ,(cl--generic-load-hist-format
508 ;; FIXME: Try to avoid re-constructing a new function if the old one 511 (cl--generic-name generic)
509 ;; is still valid (e.g. still empty method cache)? 512 qualifiers specializers))
510 (let ((gfun (cl--generic-make-function generic)) 513 current-load-list :test #'equal)
511 ;; Prevent `defalias' from recording this as the definition site of 514 ;; FIXME: Try to avoid re-constructing a new function if the old one
512 ;; the generic function. 515 ;; is still valid (e.g. still empty method cache)?
513 current-load-list) 516 (let ((gfun (cl--generic-make-function generic))
514 ;; For aliases, cl--generic-name gives us the actual name. 517 ;; Prevent `defalias' from recording this as the definition site of
515 (let ((purify-flag 518 ;; the generic function.
516 ;; BEWARE! Don't purify this function definition, since that leads 519 current-load-list
517 ;; to memory corruption if the hash-tables it holds are modified 520 ;; BEWARE! Don't purify this function definition, since that leads
518 ;; (the GC doesn't trace those pointers). 521 ;; to memory corruption if the hash-tables it holds are modified
519 nil)) 522 ;; (the GC doesn't trace those pointers).
523 (purify-flag nil))
520 ;; But do use `defalias', so that it interacts properly with nadvice, 524 ;; But do use `defalias', so that it interacts properly with nadvice,
521 ;; e.g. for tracing/debug-on-entry. 525 ;; e.g. for tracing/debug-on-entry.
522 (defalias (cl--generic-name generic) gfun))))) 526 (defalias sym gfun)))))
523 527
524(defmacro cl--generic-with-memoization (place &rest code) 528(defmacro cl--generic-with-memoization (place &rest code)
525 (declare (indent 1) (debug t)) 529 (declare (indent 1) (debug t))
@@ -1023,6 +1027,20 @@ The value returned is a list of elements of the form
1023 (push (cl--generic-method-info method) docs)))) 1027 (push (cl--generic-method-info method) docs))))
1024 docs)) 1028 docs))
1025 1029
1030(defun cl--generic-method-files (method)
1031 "Return a list of files where METHOD is defined by `cl-defmethod'.
1032The list will have entries of the form (FILE . (METHOD ...))
1033where (METHOD ...) contains the qualifiers and specializers of
1034the method and is a suitable argument for
1035`find-function-search-for-symbol'. Filenames are absolute."
1036 (let (result)
1037 (pcase-dolist (`(,file . ,defs) load-history)
1038 (dolist (def defs)
1039 (when (and (eq (car-safe def) 'cl-defmethod)
1040 (eq (cadr def) method))
1041 (push (cons file (cdr def)) result))))
1042 result))
1043
1026;;; Support for (head <val>) specializers. 1044;;; Support for (head <val>) specializers.
1027 1045
1028;; For both the `eql' and the `head' specializers, the dispatch 1046;; For both the `eql' and the `head' specializers, the dispatch
@@ -1210,5 +1228,18 @@ Used internally for the (major-mode MODE) context specializers."
1210 (progn (cl-assert (null modes)) mode) 1228 (progn (cl-assert (null modes)) mode)
1211 `(derived-mode ,mode . ,modes)))) 1229 `(derived-mode ,mode . ,modes))))
1212 1230
1231;;; Support for unloading.
1232
1233(cl-defmethod loadhist-unload-element ((x (head cl-defmethod)))
1234 (pcase-let*
1235 ((`(,name ,qualifiers . ,specializers) (cdr x))
1236 (generic (cl-generic-ensure-function name 'noerror)))
1237 (when generic
1238 (let* ((mt (cl--generic-method-table generic))
1239 (me (cl--generic-member-method specializers qualifiers mt)))
1240 (when me
1241 (setf (cl--generic-method-table generic) (delq (car me) mt)))))))
1242
1243
1213(provide 'cl-generic) 1244(provide 'cl-generic)
1214;;; cl-generic.el ends here 1245;;; cl-generic.el ends here