diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2015-03-18 23:02:26 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2015-03-18 23:02:26 -0400 |
commit | 50c117fe86d94719807cbe08353c032779b3b910 (patch) | |
tree | 9db572083112db33d17d759a245278fa0af7b897 /lisp/emacs-lisp/eieio.el | |
parent | f469024eea692a163beb98a824b5cc0a4e8bcda8 (diff) | |
download | emacs-50c117fe86d94719807cbe08353c032779b3b910.tar.gz |
EIEIO: Change class's representation to unify instance & class slots
* lisp/emacs-lisp/eieio-core.el (eieio--class): Change field names and order
to match those of cl--class; use cl--slot for both instance slots and
class slots.
(eieio--object-num-slots): Use cl-struct-slot-info.
(eieio--object-class): Rename from eieio--object-class-object.
(eieio--object-class-name): Remove.
(eieio-defclass-internal): Adjust to new slot representation.
Store doc in class rather than in `variable-documentation'.
(eieio--perform-slot-validation-for-default): Change API to take
a slot object.
(eieio--slot-override): New function.
(eieio--add-new-slot): Rewrite.
(eieio-copy-parents-into-subclass): Rewrite.
(eieio--validate-slot-value, eieio--validate-class-slot-value)
(eieio-oref-default, eieio-oset-default)
(eieio--class-slot-name-index, eieio-set-defaults): Adjust to new
slot representation.
(eieio--c3-merge-lists): Simplify.
(eieio--class/struct-parents): New function.
(eieio--class-precedence-bfs): Use it.
* lisp/emacs-lisp/eieio.el (with-slots): Use macroexp-let2.
(object-class-fast): Change recommend replacement.
(eieio-object-class): Rewrite.
(slot-exists-p): Adjust to new slot representation.
(initialize-instance): Adjust to new slot representation.
(object-write): Adjust to new slot representation.
* lisp/emacs-lisp/eieio-base.el (eieio-persistent-convert-list-to-object):
Manually map initargs to slot names.
(eieio-persistent-validate/fix-slot-value): Adjust to new
slot representation.
* lisp/emacs-lisp/eieio-compat.el (eieio--generic-static-symbol-specializers):
Extract from eieio--generic-static-symbol-generalizer.
(eieio--generic-static-symbol-generalizer): Use it.
* lisp/emacs-lisp/eieio-custom.el (eieio-object-value-create)
(eieio-object-value-get): Adjust to new slot representation.
* lisp/emacs-lisp/eieio-datadebug.el (data-debug/eieio-insert-slots):
Declare to silence warnings.
(data-debug-insert-object-button): Avoid `object-slots'.
(data-debug/eieio-insert-slots): Adjust to new slot representation.
* lisp/emacs-lisp/eieio-opt.el (eieio--help-print-slot): New function
extracted from eieio-help-class-slots.
(eieio-help-class-slots): Use it. Adjust to new slot representation.
* test/automated/eieio-test-methodinvoke.el (make-instance): Use new-style
`subclass' specializer for a change.
* test/automated/eieio-test-persist.el (persist-test-save-and-compare):
Adjust to new slot representation.
* test/automated/eieio-tests.el (eieio-test-17-virtual-slot): Don't use
initarg in `oset'.
(eieio-test-32-slot-attribute-override-2): Adjust to new
slot representation.
* lisp/emacs-lisp/cl-preloaded.el (cl--class): Fix type of `parents'.
Diffstat (limited to 'lisp/emacs-lisp/eieio.el')
-rw-r--r-- | lisp/emacs-lisp/eieio.el | 132 |
1 files changed, 70 insertions, 62 deletions
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index cdf1992f9a5..4ba67693175 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -320,19 +320,21 @@ variable name of the same name as the slot." (declare (indent 2) (debug (sexp sexp def-body))) (require 'cl-lib) ;; Transform the spec-list into a cl-symbol-macrolet spec-list. - (let ((mappings (mapcar (lambda (entry) - (let ((var (if (listp entry) (car entry) entry)) - (slot (if (listp entry) (cadr entry) entry))) - (list var `(slot-value ,object ',slot)))) - spec-list))) - (append (list 'cl-symbol-macrolet mappings) - body))) + (macroexp-let2 nil object object + `(cl-symbol-macrolet + ,(mapcar (lambda (entry) + (let ((var (if (listp entry) (car entry) entry)) + (slot (if (listp entry) (cadr entry) entry))) + (list var `(slot-value ,object ',slot)))) + spec-list) + ,@body))) ;;; Simple generators, and query functions. None of these would do ;; well embedded into an object. ;; + (define-obsolete-function-alias - 'object-class-fast #'eieio--object-class-name "24.4") + 'object-class-fast #'eieio-object-class "24.4") (cl-defgeneric eieio-object-name-string (obj) "Return a string which is OBJ's name." @@ -342,7 +344,7 @@ variable name of the same name as the slot." "Return a printed representation for object OBJ. If EXTRA, include that in the string returned to represent the symbol." (cl-check-type obj eieio-object) - (format "#<%s %s%s>" (eieio--object-class-name obj) + (format "#<%s %s%s>" (eieio-object-class obj) (eieio-object-name-string obj) (or extra ""))) (define-obsolete-function-alias 'object-name #'eieio-object-name "24.4") @@ -370,7 +372,7 @@ If EXTRA, include that in the string returned to represent the symbol." "Return the class struct defining OBJ." ;; FIXME: We say we return a "struct" but we return a symbol instead! (cl-check-type obj eieio-object) - (eieio--object-class-name obj)) + (eieio--class-name (eieio--object-class obj))) (define-obsolete-function-alias 'object-class #'eieio-object-class "24.4") ;; CLOS name, maybe? (define-obsolete-function-alias 'class-of #'eieio-object-class "24.4") @@ -378,7 +380,7 @@ If EXTRA, include that in the string returned to represent the symbol." (defun eieio-object-class-name (obj) "Return a Lisp like symbol name for OBJ's class." (cl-check-type obj eieio-object) - (eieio-class-name (eieio--object-class-object obj))) + (eieio-class-name (eieio--object-class obj))) (define-obsolete-function-alias 'object-class-name 'eieio-object-class-name "24.4") @@ -386,7 +388,7 @@ If EXTRA, include that in the string returned to represent the symbol." "Return parent classes to CLASS. (overload of variable). The CLOS function `class-direct-superclasses' is aliased to this function." - (eieio--class-parent (eieio--class-object class))) + (eieio--class-parents (eieio--class-object class))) (define-obsolete-function-alias 'class-parents #'eieio-class-parents "24.4") @@ -414,13 +416,13 @@ The CLOS function `class-direct-subclasses' is aliased to this function." (setq class (eieio--class-object class)) (cl-check-type class eieio--class) (cl-check-type obj eieio-object) - (eq (eieio--object-class-object obj) class)) + (eq (eieio--object-class obj) class)) (defun object-of-class-p (obj class) "Return non-nil if OBJ is an instance of CLASS or CLASS' subclasses." (cl-check-type obj eieio-object) ;; class will be checked one layer down - (child-of-class-p (eieio--object-class-object obj) class)) + (child-of-class-p (eieio--object-class obj) class)) ;; Backwards compatibility (defalias 'obj-of-class-p 'object-of-class-p) @@ -428,36 +430,36 @@ The CLOS function `class-direct-subclasses' is aliased to this function." "Return non-nil if CHILD class is a subclass of CLASS." (setq child (eieio--class-object child)) (cl-check-type child eieio--class) - ;; `eieio-default-superclass' is never mentioned in eieio--class-parent, + ;; `eieio-default-superclass' is never mentioned in eieio--class-parents, ;; so we have to special case it here. (or (eq class 'eieio-default-superclass) (let ((p nil)) (setq class (eieio--class-object class)) (cl-check-type class eieio--class) (while (and child (not (eq child class))) - (setq p (append p (eieio--class-parent child)) + (setq p (append p (eieio--class-parents child)) child (pop p))) (if child t)))) -(defun eieio-slot-descriptor-name (slot) slot) +(defun eieio-slot-descriptor-name (slot) + (cl--slot-descriptor-name slot)) (defun eieio-class-slots (class) "Return list of slots available in instances of CLASS." ;; FIXME: This only gives the instance slots and ignores the ;; class-allocated slots. - ;; FIXME: It only gives the slot's *names* rather than actual - ;; slot descriptors. (setq class (eieio--class-object class)) (cl-check-type class eieio--class) - (eieio--class-public-a class)) + (mapcar #'identity (eieio--class-slots class))) (defun object-slots (obj) "Return list of slots available in OBJ." (declare (obsolete eieio-class-slots "25.1")) (cl-check-type obj eieio-object) - (eieio-class-slots (eieio--object-class-object obj))) + (eieio-class-slots (eieio--object-class obj))) -(defun eieio--class-slot-initarg (class slot) "Fetch from CLASS, SLOT's :initarg." +(defun eieio--class-slot-initarg (class slot) + "Fetch from CLASS, SLOT's :initarg." (cl-check-type class eieio--class) (let ((ia (eieio--class-initarg-tuples class)) (f nil)) @@ -507,12 +509,18 @@ OBJECT can be an instance or a class." (defun slot-exists-p (object-or-class slot) "Return non-nil if OBJECT-OR-CLASS has SLOT." (let ((cv (cond ((eieio-object-p object-or-class) - (eieio--object-class-object object-or-class)) + (eieio--object-class object-or-class)) ((eieio--class-p object-or-class) object-or-class) (t (find-class object-or-class 'error))))) - (or (memq slot (eieio--class-public-a cv)) - (memq slot (eieio--class-class-allocation-a cv))) - )) + (or (gethash slot (eieio--class-index-table cv)) + ;; FIXME: We could speed this up by adding class slots into the + ;; index-table (e.g. with a negative index?). + (let ((cs (eieio--class-class-slots cv)) + found) + (dotimes (i (length cs)) + (if (eq slot (cl--slot-descriptor-name (aref cs i))) + (setq found t))) + found)))) (defun find-class (symbol &optional errorp) "Return the class that SYMBOL represents. @@ -671,7 +679,7 @@ Called from the constructor routine.") "Set slots of OBJ with SLOTS which is a list of name/value pairs. Called from the constructor routine." (while slots - (let ((rn (eieio--initarg-to-attribute (eieio--object-class-object obj) + (let ((rn (eieio--initarg-to-attribute (eieio--object-class obj) (car slots)))) (if (not rn) (slot-missing obj (car slots) 'oset (car (cdr slots))) @@ -694,9 +702,9 @@ not taken, then new objects of your class will not have their values dynamically set from SLOTS." ;; First, see if any of our defaults are `lambda', and ;; re-evaluate them and apply the value to our slots. - (let* ((this-class (eieio--object-class-object this)) - (defaults (eieio--class-public-d this-class))) - (dolist (slot (eieio--class-public-a this-class)) + (let* ((this-class (eieio--object-class this)) + (slots (eieio--class-slots this-class))) + (dotimes (i (length slots)) ;; For each slot, see if we need to evaluate it. ;; ;; Paul Landes said in an email: @@ -704,11 +712,12 @@ dynamically set from SLOTS." ;; > the quoted thing as you already have. This is by the ;; > Sonya E. Keene book and other things I've look at on the ;; > web. - (let ((dflt (eieio-default-eval-maybe (car defaults)))) - (when (not (eq dflt (car defaults))) - (eieio-oset this slot dflt) )) - ;; Next. - (setq defaults (cdr defaults)))) + (let* ((slot (aref slots i)) + (initform (cl--slot-descriptor-initform slot)) + (dflt (eieio-default-eval-maybe initform))) + (when (not (eq dflt initform)) + ;; FIXME: We should be able to just do (aset this (+ i <cst>) dflt)! + (eieio-oset this (cl--slot-descriptor-name slot) dflt))))) ;; Shared initialize will parse our slots for us. (shared-initialize this slots)) @@ -825,32 +834,31 @@ this object." (prin1 (eieio-object-name-string this)) (princ "\n") ;; Loop over all the public slots - (let ((publa (eieio--class-public-a cv)) - (publd (eieio--class-public-d cv)) - (publp (eieio--class-public-printer cv)) + (let ((slots (eieio--class-slots cv)) (eieio-print-depth (1+ eieio-print-depth))) - (while publa - (when (slot-boundp this (car publa)) - (let ((i (eieio--class-slot-initarg cv (car publa))) - (v (eieio-oref this (car publa))) - ) - (unless (or (not i) (equal v (car publd))) - (unless (bolp) - (princ "\n")) - (princ (make-string (* eieio-print-depth 2) ? )) - (princ (symbol-name i)) - (if (car publp) - ;; Use our public printer - (progn - (princ " ") - (funcall (car publp) v)) - ;; Use our generic override prin1 function. - (princ (if (or (eieio-object-p v) - (eieio-object-p (car-safe v))) - "\n" " ")) - (eieio-override-prin1 v))))) - (setq publa (cdr publa) publd (cdr publd) - publp (cdr publp)))) + (dotimes (i (length slots)) + (let ((slot (aref slots i))) + (when (slot-boundp this (cl--slot-descriptor-name slot)) + (let ((i (eieio--class-slot-initarg + cv (cl--slot-descriptor-name slot))) + (v (eieio-oref this (cl--slot-descriptor-name slot)))) + (unless (or (not i) (equal v (cl--slot-descriptor-initform slot))) + (unless (bolp) + (princ "\n")) + (princ (make-string (* eieio-print-depth 2) ? )) + (princ (symbol-name i)) + (if (alist-get :printer (cl--slot-descriptor-props slot)) + ;; Use our public printer + (progn + (princ " ") + (funcall (alist-get :printer + (cl--slot-descriptor-props slot)) + v)) + ;; Use our generic override prin1 function. + (princ (if (or (eieio-object-p v) + (eieio-object-p (car-safe v))) + "\n" " ")) + (eieio-override-prin1 v)))))))) (princ ")") (when (= eieio-print-depth 0) (princ "\n")))) @@ -919,7 +927,7 @@ variable PRINT-FUNCTION. Optional argument NOESCAPE is passed to ;;; Start of automatically extracted autoloads. -;;;### (autoloads nil "eieio-custom" "eieio-custom.el" "2ec91e473fcad1ff20cd76edc4aab706") +;;;### (autoloads nil "eieio-custom" "eieio-custom.el" "813d32fbf76d4248fc6b4dc97ebcd720") ;;; Generated autoloads from eieio-custom.el (autoload 'customize-object "eieio-custom" "\ @@ -930,7 +938,7 @@ Optional argument GROUP is the sub-group of slots to display. ;;;*** -;;;### (autoloads nil "eieio-opt" "eieio-opt.el" "d1910eb455f102989fc33bb3f5a9b614") +;;;### (autoloads nil "eieio-opt" "eieio-opt.el" "3005b815c6b30eccbf0642170b3f82a5") ;;; Generated autoloads from eieio-opt.el (autoload 'eieio-browse "eieio-opt" "\ |