diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2021-06-12 16:22:03 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2021-06-12 16:22:03 -0400 |
commit | 4c6554413d318069239ba83f4f42fa2452801d30 (patch) | |
tree | 24c40c07b69d2e633fd38235094d46ce008b7680 /lisp/emacs-lisp/eieio.el | |
parent | 0afab352e02d7070a8ced2af53c1d01217400cdf (diff) | |
download | emacs-4c6554413d318069239ba83f4f42fa2452801d30.tar.gz emacs-4c6554413d318069239ba83f4f42fa2452801d30.tar.bz2 emacs-4c6554413d318069239ba83f4f42fa2452801d30.zip |
EIEIO: Promote the CLOS behavior over the EIEIO-specific behavior
Change docs to advertize `slot-value` rather than `oref`.
Change the implementation of `:initform` to better match the CLOS semantics,
while preserving the EIEIO semantics, but warn when encountering cases
where the two diverge.
Demote the mostly unused special semantics of `oref-default`
on non-class allocated slots.
* doc/misc/eieio.texi (Quick Start): Use `slot-value`.
(Accessing Slots): Move `slot-value` before `oref`.
Fix paren-typo in example (reported by pillule <pillule@riseup.net>).
(Introspection): Remove mention of `class-slot-initarg`.
* lisp/transient.el (transient--parse-group, transient--parse-suffix):
Don't use `oref-default` to get the default value.
(transient-lisp-variable): Init forms are evaluated.
* lisp/emacs-lisp/eieio.el (defclass): Warn about inapplicable
`:initarg` and about uses of init forms that are ambiguous.
(oref): Don't advertize the deprecated use of initargs as slot names.
(oref-default): Don't advertize the deprecated case where it returns the
initform's value.
(initialize-instance): Use `macroexp-const-p`.
* lisp/emacs-lisp/eieio-core.el (eieio--unbound): Rename from
`eieio-unbound`.
(eieio--unbound-form): New var.
(eieio--slot-override): Use it.
(eieio-defclass-internal): Use it. Change `init` so it should always
be evaluated.
(eieio--known-class-slot-names): New var.
(eieio--eval-default-p): Rename from `eieio-eval-default-p`.
(eieio--perform-slot-validation-for-default): Use `macroexp-const-p` to
decide whether to skip the test.
(eieio--add-new-slot): Register slot in `eieio--known-class-slot-names`
when applicable.
(eieio-oref-default, eieio-oset-default): Add warning for unknown slots
and slots not known to be allocated to the class.
(eieio-default-eval-maybe): Delete function. Use just `eval` instead.
(eieio-declare-slots): Allow slots to specify their allocation class.
* lisp/cedet/srecode/insert.el (point): Declare the slot instead of
moving the class definition before the slot's first use.
(srecode-template-inserter-point, srecode-insert-fcn):
Use nil instead of unbound for the `point` slot.
* lisp/cedet/srecode/compile.el (srecode-template-inserter):
Declare the `key` slot that all children should have.
* lisp/emacs-lisp/eieio-speedbar.el (eieio-speedbar)
(eieio-speedbar-directory-button, eieio-speedbar-file-button):
* lisp/emacs-lisp/eieio-custom.el (eieio-widget-test-class):
* lisp/emacs-lisp/chart.el (chart-bar):
* lisp/cedet/semantic/ede-grammar.el (semantic-ede-proj-target-grammar):
* lisp/cedet/semantic/db.el (semanticdb-project-database):
* lisp/cedet/semantic/db-javascript.el (semanticdb-table-javascript)
(semanticdb-project-database-javascript):
* lisp/cedet/semantic/db-el.el (semanticdb-table-emacs-lisp)
(semanticdb-project-database-emacs-lisp):
* lisp/cedet/semantic/db-ebrowse.el (semanticdb-table-ebrowse)
(semanticdb-project-database-ebrowse):
* lisp/cedet/ede/proj.el (ede-proj-project):
* lisp/cedet/ede/proj-obj.el (ede-proj-target-makefile-objectcode):
* lisp/cedet/ede/generic.el (ede-generic-project):
* lisp/cedet/ede/config.el (ede-project-with-config):
* lisp/cedet/ede/base.el (ede-target, ede-project):
* lisp/auth-source.el (auth-source-backend): Init forms are evaluated,
so quote them accordingly.
Diffstat (limited to 'lisp/emacs-lisp/eieio.el')
-rw-r--r-- | lisp/emacs-lisp/eieio.el | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 31b6b0945bb..1c8c372aaef 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -131,6 +131,7 @@ and reference them using the function `class-option'." (let ((testsym1 (intern (concat (symbol-name name) "-p"))) (testsym2 (intern (format "%s--eieio-childp" name))) + (warnings '()) (accessors ())) ;; Collect the accessors we need to define. @@ -145,6 +146,8 @@ and reference them using the function `class-option'." ;; Update eieio--known-slot-names already in case we compile code which ;; uses this before the class is loaded. (cl-pushnew sname eieio--known-slot-names) + (when (eq alloc :class) + (cl-pushnew sname eieio--known-class-slot-names)) (if eieio-error-unsupported-class-tags (let ((tmp soptions)) @@ -176,8 +179,22 @@ and reference them using the function `class-option'." (signal 'invalid-slot-type (list :label label))) ;; Is there an initarg, but allocation of class? - (if (and initarg (eq alloc :class)) - (message "Class allocated slots do not need :initarg")) + (when (and initarg (eq alloc :class)) + (push (format "Meaningless :initarg for class allocated slot '%S'" + sname) + warnings)) + + (let ((init (plist-get soptions :initform))) + (unless (or (macroexp-const-p init) + (eieio--eval-default-p init)) + ;; FIXME: Historically, EIEIO used a heuristic to try and guess + ;; whether the initform is a form to be evaluated or just + ;; a constant. We use `eieio--eval-default-p' to see what the + ;; heuristic says and if it disagrees with normal evaluation + ;; then tweak the initform to make it fit and emit + ;; a warning accordingly. + (push (format "Ambiguous initform needs quoting: %S" init) + warnings))) ;; Anyone can have an accessor function. This creates a function ;; of the specified name, and also performs a `defsetf' if applicable @@ -223,6 +240,8 @@ This method is obsolete." )) `(progn + ,@(mapcar (lambda (w) (macroexp-warn-and-return w `(progn ',w) 'compile-only)) + warnings) ;; This test must be created right away so we can have self- ;; referencing classes. ei, a class whose slot can contain only ;; pointers to itself. @@ -282,9 +301,7 @@ This method is obsolete." ;;; Get/Set slots in an object. ;; (defmacro oref (obj slot) - "Retrieve the value stored in OBJ in the slot named by SLOT. -Slot is the name of the slot when created by `defclass' or the label -created by the :initarg tag." + "Retrieve the value stored in OBJ in the slot named by SLOT." (declare (debug (form symbolp))) `(eieio-oref ,obj (quote ,slot))) @@ -292,13 +309,11 @@ created by the :initarg tag." (defalias 'set-slot-value #'eieio-oset) (make-obsolete 'set-slot-value "use (setf (slot-value ..) ..) instead" "25.1") -(defmacro oref-default (obj slot) - "Get the default value of OBJ (maybe a class) for SLOT. -The default value is the value installed in a class with the :initform -tag. SLOT can be the slot name, or the tag specified by the :initarg -tag in the `defclass' call." +(defmacro oref-default (class slot) + "Get the value of class allocated slot SLOT. +CLASS can also be an object, in which case we use the object's class." (declare (debug (form symbolp))) - `(eieio-oref-default ,obj (quote ,slot))) + `(eieio-oref-default ,class (quote ,slot))) ;;; Handy CLOS macros ;; @@ -538,11 +553,11 @@ OBJECT can be an instance or a class." ((eieio-object-p object) (eieio-oref object slot)) ((symbolp object) (eieio-oref-default object slot)) (t (signal 'wrong-type-argument (list 'eieio-object-p object)))) - eieio-unbound)))) + eieio--unbound)))) (defun slot-makeunbound (object slot) "In OBJECT, make SLOT unbound." - (eieio-oset object slot eieio-unbound)) + (eieio-oset object slot eieio--unbound)) (defun slot-exists-p (object-or-class slot) "Return non-nil if OBJECT-OR-CLASS has SLOT." @@ -740,18 +755,14 @@ dynamically set from SLOTS." (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: - ;; > CL evaluates it if it can, and otherwise, leaves it as - ;; > 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* ((slot (aref slots i)) - (initform (cl--slot-descriptor-initform slot)) - (dflt (eieio-default-eval-maybe initform))) - (when (not (eq dflt initform)) + (initform (cl--slot-descriptor-initform slot))) + ;; Those slots whose initform is constant already have the right + ;; value set in the default-object. + (unless (macroexp-const-p initform) ;; FIXME: We should be able to just do (aset this (+ i <cst>) dflt)! - (eieio-oset this (cl--slot-descriptor-name slot) dflt))))) + (eieio-oset this (cl--slot-descriptor-name slot) + (eval initform t)))))) ;; Shared initialize will parse our slots for us. (shared-initialize this slots)) |