summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/eieio.el
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2015-03-18 23:02:26 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2015-03-18 23:02:26 -0400
commit50c117fe86d94719807cbe08353c032779b3b910 (patch)
tree9db572083112db33d17d759a245278fa0af7b897 /lisp/emacs-lisp/eieio.el
parentf469024eea692a163beb98a824b5cc0a4e8bcda8 (diff)
downloademacs-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.el132
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" "\