diff options
| author | Stefan Monnier | 2015-01-08 15:47:32 -0500 |
|---|---|---|
| committer | Stefan Monnier | 2015-01-08 15:47:32 -0500 |
| commit | 6a67b20ddd458d71a1d63746504d91b1acea9b2b (patch) | |
| tree | 38ff716a76899e0638246d28d6a465b8dcf50522 | |
| parent | 54181569d255322bdae321dc3fddeb465780fbe0 (diff) | |
| download | emacs-6a67b20ddd458d71a1d63746504d91b1acea9b2b.tar.gz emacs-6a67b20ddd458d71a1d63746504d91b1acea9b2b.zip | |
* lisp/emacs-lisp/eieio*.el: Move the function defs to defclass.
* lisp/emacs-lisp/eieio.el (defclass): Move from eieio-defclass all the code
that creates functions, and most of the sanity checks.
Mark as obsolete the <class>-child-p function.
* lisp/emacs-lisp/eieio-core.el (eieio--define-field-accessors): Remove.
(eieio--class, eieio--object): Use cl-defstruct.
(eieio--object-num-slots): Define manually.
(eieio-defclass-autoload): Use eieio--class-make.
(eieio-defclass-internal): Rename from eieio-defclass. Move all the
`(lambda...) definitions and most of the sanity checks to `defclass'.
Mark as obsolete the <class>-list-p function, the <class> variable and
the <initarg> variables. Use pcase-dolist.
(eieio-defclass): New compatibility function.
* lisp/emacs-lisp/eieio-opt.el (eieio-build-class-alist)
(eieio-class-speedbar): Don't use eieio-default-superclass var.
| -rw-r--r-- | etc/NEWS | 7 | ||||
| -rw-r--r-- | lisp/ChangeLog | 18 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-core.el | 358 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-opt.el | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio.el | 186 |
5 files changed, 301 insertions, 272 deletions
| @@ -1,6 +1,6 @@ | |||
| 1 | GNU Emacs NEWS -- history of user-visible changes. | 1 | GNU Emacs NEWS -- history of user-visible changes. |
| 2 | 2 | ||
| 3 | Copyright (C) 2014 Free Software Foundation, Inc. | 3 | Copyright (C) 2014, 2015 Free Software Foundation, Inc. |
| 4 | See the end of the file for license conditions. | 4 | See the end of the file for license conditions. |
| 5 | 5 | ||
| 6 | Please send Emacs bug reports to bug-gnu-emacs@gnu.org. | 6 | Please send Emacs bug reports to bug-gnu-emacs@gnu.org. |
| @@ -187,6 +187,11 @@ Unicode standards. | |||
| 187 | 187 | ||
| 188 | 188 | ||
| 189 | * Changes in Specialized Modes and Packages in Emacs 25.1 | 189 | * Changes in Specialized Modes and Packages in Emacs 25.1 |
| 190 | |||
| 191 | ** EIEIO | ||
| 192 | *** The <class>-list-p and <class>-child-p functions are declared obsolete. | ||
| 193 | *** The <class> variables are declared obsolete. | ||
| 194 | *** The <initarg> variables are declared obsolete. | ||
| 190 | ** ido | 195 | ** ido |
| 191 | *** New command `ido-bury-buffer-at-head' bound to C-S-b | 196 | *** New command `ido-bury-buffer-at-head' bound to C-S-b |
| 192 | Bury the buffer at the head of `ido-matches', analogous to how C-k | 197 | Bury the buffer at the head of `ido-matches', analogous to how C-k |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 66b3b8eb061..6d7bfae31ce 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,9 +1,27 @@ | |||
| 1 | 2015-01-08 Stefan Monnier <monnier@iro.umontreal.ca> | 1 | 2015-01-08 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 2 | ||
| 3 | * emacs-lisp/eieio.el (defclass): Move from eieio-defclass all the code | ||
| 4 | that creates functions, and most of the sanity checks. | ||
| 5 | Mark as obsolete the <class>-child-p function. | ||
| 6 | * emacs-lisp/eieio-core.el (eieio--define-field-accessors): Remove. | ||
| 7 | (eieio--class, eieio--object): Use cl-defstruct. | ||
| 8 | (eieio--object-num-slots): Define manually. | ||
| 9 | (eieio-defclass-autoload): Use eieio--class-make. | ||
| 10 | (eieio-defclass-internal): Rename from eieio-defclass. Move all the | ||
| 11 | `(lambda...) definitions and most of the sanity checks to `defclass'. | ||
| 12 | Mark as obsolete the <class>-list-p function, the <class> variable and | ||
| 13 | the <initarg> variables. Use pcase-dolist. | ||
| 14 | (eieio-defclass): New compatibility function. | ||
| 15 | * emacs-lisp/eieio-opt.el (eieio-build-class-alist) | ||
| 16 | (eieio-class-speedbar): Don't use eieio-default-superclass var. | ||
| 17 | |||
| 18 | 2015-01-08 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 19 | |||
| 3 | * emacs-lisp/eieio-generic.el: New file. | 20 | * emacs-lisp/eieio-generic.el: New file. |
| 4 | * emacs-lisp/eieio-core.el: Move all generic function code to | 21 | * emacs-lisp/eieio-core.el: Move all generic function code to |
| 5 | eieio-generic.el. | 22 | eieio-generic.el. |
| 6 | (eieio--defmethod): Declare. | 23 | (eieio--defmethod): Declare. |
| 24 | |||
| 7 | * emacs-lisp/eieio.el: Require eieio-generic. Move all generic | 25 | * emacs-lisp/eieio.el: Require eieio-generic. Move all generic |
| 8 | function code to eieio-generic.el. | 26 | function code to eieio-generic.el. |
| 9 | * emacs-lisp/eieio-opt.el (eieio-help-generic): Move to | 27 | * emacs-lisp/eieio-opt.el (eieio-help-generic): Move to |
diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index fba4d8f50c7..dc2c873eb42 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | ;;; Code: | 32 | ;;; Code: |
| 33 | 33 | ||
| 34 | (require 'cl-lib) | 34 | (require 'cl-lib) |
| 35 | (require 'pcase) | ||
| 35 | 36 | ||
| 36 | (put 'eieio--defalias 'byte-hunk-handler | 37 | (put 'eieio--defalias 'byte-hunk-handler |
| 37 | #'byte-compile-file-form-defalias) ;;(get 'defalias 'byte-hunk-handler) | 38 | #'byte-compile-file-form-defalias) ;;(get 'defalias 'byte-hunk-handler) |
| @@ -117,66 +118,70 @@ Currently under control of this var: | |||
| 117 | `(let ((eieio--scoped-class-stack (cons ,class eieio--scoped-class-stack))) | 118 | `(let ((eieio--scoped-class-stack (cons ,class eieio--scoped-class-stack))) |
| 118 | ,@forms)) | 119 | ,@forms)) |
| 119 | 120 | ||
| 120 | ;;; | 121 | (progn |
| 121 | ;; Field Accessors | 122 | ;; Arrange for field access not to bother checking if the access is indeed |
| 122 | ;; | 123 | ;; made to an eieio--class object. |
| 123 | (defmacro eieio--define-field-accessors (prefix fields) | 124 | (cl-declaim (optimize (safety 0))) |
| 124 | (declare (indent 1)) | 125 | (cl-defstruct (eieio--class |
| 125 | (let ((index 0) | 126 | (:constructor nil) |
| 126 | (defs '())) | 127 | (:constructor eieio--class-make (symbol &aux (tag 'defclass))) |
| 127 | (dolist (field fields) | 128 | (:type vector) |
| 128 | (let ((doc (if (listp field) | 129 | (:copier nil)) |
| 129 | (prog1 (cadr field) (setq field (car field)))))) | 130 | ;; We use an untagged cl-struct, with our own hand-made tag as first field |
| 130 | (push `(defmacro ,(intern (format "eieio--%s-%s" prefix field)) (x) | 131 | ;; (containing the symbol `defclass'). It would be better to use a normal |
| 131 | ,@(if doc (list (format (if (string-match "\n" doc) | 132 | ;; cl-struct with its normal tag (e.g. so that cl-defstruct can define the |
| 132 | "Return %s" "Return %s of a %s.") | 133 | ;; predicate for us), but that breaks compatibility with .elc files compiled |
| 133 | doc prefix))) | 134 | ;; against older versions of EIEIO. |
| 134 | (list 'aref x ,index)) | 135 | tag |
| 135 | defs) | 136 | symbol ;; symbol (self-referencing) |
| 136 | (setq index (1+ index)))) | 137 | parent children |
| 137 | `(eval-and-compile | 138 | symbol-hashtable ;; hashtable permitting fast access to variable position indexes |
| 138 | ,@(nreverse defs) | 139 | ;; @todo |
| 139 | (defconst ,(intern (format "eieio--%s-num-slots" prefix)) ,index)))) | 140 | ;; the word "public" here is leftovers from the very first version. |
| 140 | 141 | ;; Get rid of it! | |
| 141 | (eieio--define-field-accessors class | 142 | public-a ;; class attribute index |
| 142 | (-unused-0 ;;Constant slot, set to `defclass'. | 143 | public-d ;; class attribute defaults index |
| 143 | (symbol "symbol (self-referencing)") | 144 | public-doc ;; class documentation strings for attributes |
| 144 | parent children | 145 | public-type ;; class type for a slot |
| 145 | (symbol-hashtable "hashtable permitting fast access to variable position indexes") | 146 | public-custom ;; class custom type for a slot |
| 146 | ;; @todo | 147 | public-custom-label ;; class custom group for a slot |
| 147 | ;; the word "public" here is leftovers from the very first version. | 148 | public-custom-group ;; class custom group for a slot |
| 148 | ;; Get rid of it! | 149 | public-printer ;; printer for a slot |
| 149 | (public-a "class attribute index") | 150 | protection ;; protection for a slot |
| 150 | (public-d "class attribute defaults index") | 151 | initarg-tuples ;; initarg tuples list |
| 151 | (public-doc "class documentation strings for attributes") | 152 | class-allocation-a ;; class allocated attributes |
| 152 | (public-type "class type for a slot") | 153 | class-allocation-doc ;; class allocated documentation |
| 153 | (public-custom "class custom type for a slot") | 154 | class-allocation-type ;; class allocated value type |
| 154 | (public-custom-label "class custom group for a slot") | 155 | class-allocation-custom ;; class allocated custom descriptor |
| 155 | (public-custom-group "class custom group for a slot") | 156 | class-allocation-custom-label ;; class allocated custom descriptor |
| 156 | (public-printer "printer for a slot") | 157 | class-allocation-custom-group ;; class allocated custom group |
| 157 | (protection "protection for a slot") | 158 | class-allocation-printer ;; class allocated printer for a slot |
| 158 | (initarg-tuples "initarg tuples list") | 159 | class-allocation-protection ;; class allocated protection list |
| 159 | (class-allocation-a "class allocated attributes") | 160 | class-allocation-values ;; class allocated value vector |
| 160 | (class-allocation-doc "class allocated documentation") | 161 | default-object-cache ;; what a newly created object would look like. |
| 161 | (class-allocation-type "class allocated value type") | 162 | ; This will speed up instantiation time as |
| 162 | (class-allocation-custom "class allocated custom descriptor") | 163 | ; only a `copy-sequence' will be needed, instead of |
| 163 | (class-allocation-custom-label "class allocated custom descriptor") | 164 | ; looping over all the values and setting them from |
| 164 | (class-allocation-custom-group "class allocated custom group") | 165 | ; the default. |
| 165 | (class-allocation-printer "class allocated printer for a slot") | 166 | options ;; storage location of tagged class option |
| 166 | (class-allocation-protection "class allocated protection list") | 167 | ; Stored outright without modifications or stripping |
| 167 | (class-allocation-values "class allocated value vector") | 168 | ) |
| 168 | (default-object-cache "what a newly created object would look like. | 169 | ;; Set it back to the default value. |
| 169 | This will speed up instantiation time as only a `copy-sequence' will | 170 | (cl-declaim (optimize (safety 1)))) |
| 170 | be needed, instead of looping over all the values and setting them | 171 | |
| 171 | from the default.") | 172 | |
| 172 | (options "storage location of tagged class options. | 173 | (cl-defstruct (eieio--object |
| 173 | Stored outright without modifications or stripping."))) | 174 | (:type vector) ;We manage our own tagging system. |
| 174 | 175 | (:constructor nil) | |
| 175 | (eieio--define-field-accessors object | 176 | (:copier nil)) |
| 176 | ;; `class-tag' holds a symbol, which is not the class name, but is instead | 177 | ;; `class-tag' holds a symbol, which is not the class name, but is instead |
| 177 | ;; properly prefixed as an internal EIEIO thingy and which holds the class | 178 | ;; properly prefixed as an internal EIEIO thingy and which holds the class |
| 178 | ;; object/struct in its `symbol-value' slot. | 179 | ;; object/struct in its `symbol-value' slot. |
| 179 | ((class-tag "tag containing the class struct"))) | 180 | class-tag) |
| 181 | |||
| 182 | (eval-and-compile | ||
| 183 | (defconst eieio--object-num-slots | ||
| 184 | (length (get 'eieio--object 'cl-struct-slots)))) | ||
| 180 | 185 | ||
| 181 | (defsubst eieio--object-class-object (obj) | 186 | (defsubst eieio--object-class-object (obj) |
| 182 | (symbol-value (eieio--object-class-tag obj))) | 187 | (symbol-value (eieio--object-class-tag obj))) |
| @@ -297,15 +302,11 @@ It creates an autoload function for CNAME's constructor." | |||
| 297 | ;; Assume we've already debugged inputs. | 302 | ;; Assume we've already debugged inputs. |
| 298 | 303 | ||
| 299 | (let* ((oldc (when (class-p cname) (eieio--class-v cname))) | 304 | (let* ((oldc (when (class-p cname) (eieio--class-v cname))) |
| 300 | (newc (make-vector eieio--class-num-slots nil)) | 305 | (newc (eieio--class-make cname)) |
| 301 | ) | 306 | ) |
| 302 | (if oldc | 307 | (if oldc |
| 303 | nil ;; Do nothing if we already have this class. | 308 | nil ;; Do nothing if we already have this class. |
| 304 | 309 | ||
| 305 | ;; Create the class in NEWC, but don't fill anything else in. | ||
| 306 | (aset newc 0 'defclass) | ||
| 307 | (setf (eieio--class-symbol newc) cname) | ||
| 308 | |||
| 309 | (let ((clear-parent nil)) | 310 | (let ((clear-parent nil)) |
| 310 | ;; No parents? | 311 | ;; No parents? |
| 311 | (when (not superclasses) | 312 | (when (not superclasses) |
| @@ -333,7 +334,8 @@ It creates an autoload function for CNAME's constructor." | |||
| 333 | 334 | ||
| 334 | ;; turn this into a usable self-pointing symbol | 335 | ;; turn this into a usable self-pointing symbol |
| 335 | (when eieio-backward-compatibility | 336 | (when eieio-backward-compatibility |
| 336 | (set cname cname)) | 337 | (set cname cname) |
| 338 | (make-obsolete-variable cname (format "use '%s instead" cname) "25.1")) | ||
| 337 | 339 | ||
| 338 | ;; Store the new class vector definition into the symbol. We need to | 340 | ;; Store the new class vector definition into the symbol. We need to |
| 339 | ;; do this first so that we can call defmethod for the accessor. | 341 | ;; do this first so that we can call defmethod for the accessor. |
| @@ -364,11 +366,10 @@ It creates an autoload function for CNAME's constructor." | |||
| 364 | 366 | ||
| 365 | (declare-function eieio--defmethod "eieio-generic" (method kind argclass code)) | 367 | (declare-function eieio--defmethod "eieio-generic" (method kind argclass code)) |
| 366 | 368 | ||
| 367 | (defun eieio-defclass (cname superclasses slots options-and-doc) | 369 | (defun eieio-defclass-internal (cname superclasses slots options) |
| 368 | ;; FIXME: Most of this should be moved to the `defclass' macro. | ||
| 369 | "Define CNAME as a new subclass of SUPERCLASSES. | 370 | "Define CNAME as a new subclass of SUPERCLASSES. |
| 370 | SLOTS are the slots residing in that class definition, and options or | 371 | SLOTS are the slots residing in that class definition, and OPTIONS |
| 371 | documentation OPTIONS-AND-DOC is the toplevel documentation for this class. | 372 | holds the class options. |
| 372 | See `defclass' for more information." | 373 | See `defclass' for more information." |
| 373 | ;; Run our eieio-hook each time, and clear it when we are done. | 374 | ;; Run our eieio-hook each time, and clear it when we are done. |
| 374 | ;; This way people can add hooks safely if they want to modify eieio | 375 | ;; This way people can add hooks safely if they want to modify eieio |
| @@ -376,18 +377,12 @@ See `defclass' for more information." | |||
| 376 | (run-hooks 'eieio-hook) | 377 | (run-hooks 'eieio-hook) |
| 377 | (setq eieio-hook nil) | 378 | (setq eieio-hook nil) |
| 378 | 379 | ||
| 379 | (eieio--check-type listp superclasses) | ||
| 380 | |||
| 381 | (let* ((pname superclasses) | 380 | (let* ((pname superclasses) |
| 382 | (newc (make-vector eieio--class-num-slots nil)) | 381 | (newc (eieio--class-make cname)) |
| 383 | (oldc (when (class-p cname) (eieio--class-v cname))) | 382 | (oldc (when (class-p cname) (eieio--class-v cname))) |
| 384 | (groups nil) ;; list of groups id'd from slots | 383 | (groups nil) ;; list of groups id'd from slots |
| 385 | (options nil) | ||
| 386 | (clearparent nil)) | 384 | (clearparent nil)) |
| 387 | 385 | ||
| 388 | (aset newc 0 'defclass) | ||
| 389 | (setf (eieio--class-symbol newc) cname) | ||
| 390 | |||
| 391 | ;; If this class already existed, and we are updating its structure, | 386 | ;; If this class already existed, and we are updating its structure, |
| 392 | ;; make sure we keep the old child list. This can cause bugs, but | 387 | ;; make sure we keep the old child list. This can cause bugs, but |
| 393 | ;; if no new slots are created, it also saves time, and prevents | 388 | ;; if no new slots are created, it also saves time, and prevents |
| @@ -403,19 +398,6 @@ See `defclass' for more information." | |||
| 403 | (setf (eieio--class-children newc) children) | 398 | (setf (eieio--class-children newc) children) |
| 404 | (remhash cname eieio-defclass-autoload-map)))) | 399 | (remhash cname eieio-defclass-autoload-map)))) |
| 405 | 400 | ||
| 406 | (cond ((and (stringp (car options-and-doc)) | ||
| 407 | (/= 1 (% (length options-and-doc) 2))) | ||
| 408 | (error "Too many arguments to `defclass'")) | ||
| 409 | ((and (symbolp (car options-and-doc)) | ||
| 410 | (/= 0 (% (length options-and-doc) 2))) | ||
| 411 | (error "Too many arguments to `defclass'")) | ||
| 412 | ) | ||
| 413 | |||
| 414 | (setq options | ||
| 415 | (if (stringp (car options-and-doc)) | ||
| 416 | (cons :documentation options-and-doc) | ||
| 417 | options-and-doc)) | ||
| 418 | |||
| 419 | (if pname | 401 | (if pname |
| 420 | (progn | 402 | (progn |
| 421 | (dolist (p pname) | 403 | (dolist (p pname) |
| @@ -447,52 +429,13 @@ See `defclass' for more information." | |||
| 447 | 429 | ||
| 448 | ;; turn this into a usable self-pointing symbol; FIXME: Why? | 430 | ;; turn this into a usable self-pointing symbol; FIXME: Why? |
| 449 | (when eieio-backward-compatibility | 431 | (when eieio-backward-compatibility |
| 450 | (set cname cname)) | 432 | (set cname cname) |
| 451 | 433 | (make-obsolete-variable cname (format "use '%s instead" cname) "25.1")) | |
| 452 | ;; These two tests must be created right away so we can have self- | ||
| 453 | ;; referencing classes. ei, a class whose slot can contain only | ||
| 454 | ;; pointers to itself. | ||
| 455 | |||
| 456 | ;; Create the test function | ||
| 457 | (let ((csym (intern (concat (symbol-name cname) "-p")))) | ||
| 458 | (fset csym | ||
| 459 | `(lambda (obj) | ||
| 460 | ,(format "Test OBJ to see if it an object of type %s" cname) | ||
| 461 | (and (eieio-object-p obj) | ||
| 462 | (same-class-p obj ',cname))))) | ||
| 463 | |||
| 464 | ;; Make sure the method invocation order is a valid value. | ||
| 465 | (let ((io (eieio--class-option-assoc options :method-invocation-order))) | ||
| 466 | (when (and io (not (member io '(:depth-first :breadth-first :c3)))) | ||
| 467 | (error "Method invocation order %s is not allowed" io) | ||
| 468 | )) | ||
| 469 | |||
| 470 | ;; Create a handy child test too | ||
| 471 | (let ((csym (if eieio-backward-compatibility | ||
| 472 | (intern (concat (symbol-name cname) "-child-p")) | ||
| 473 | (make-symbol (concat (symbol-name cname) "-child-p"))))) | ||
| 474 | (fset csym | ||
| 475 | `(lambda (obj) | ||
| 476 | ,(format | ||
| 477 | "Test OBJ to see if it an object is a child of type %s" | ||
| 478 | cname) | ||
| 479 | (and (eieio-object-p obj) | ||
| 480 | (object-of-class-p obj ',cname)))) | ||
| 481 | |||
| 482 | ;; When using typep, (typep OBJ 'myclass) returns t for objects which | ||
| 483 | ;; are subclasses of myclass. For our predicates, however, it is | ||
| 484 | ;; important for EIEIO to be backwards compatible, where | ||
| 485 | ;; myobject-p, and myobject-child-p are different. | ||
| 486 | ;; "cl" uses this technique to specify symbols with specific typep | ||
| 487 | ;; test, so we can let typep have the CLOS documented behavior | ||
| 488 | ;; while keeping our above predicate clean. | ||
| 489 | |||
| 490 | (put cname 'cl-deftype-satisfies csym)) | ||
| 491 | 434 | ||
| 492 | ;; Create a handy list of the class test too | 435 | ;; Create a handy list of the class test too |
| 493 | (when eieio-backward-compatibility | 436 | (when eieio-backward-compatibility |
| 494 | (let ((csym (intern (concat (symbol-name cname) "-list-p")))) | 437 | (let ((csym (intern (concat (symbol-name cname) "-list-p")))) |
| 495 | (fset csym | 438 | (defalias csym |
| 496 | `(lambda (obj) | 439 | `(lambda (obj) |
| 497 | ,(format | 440 | ,(format |
| 498 | "Test OBJ to see if it a list of objects which are a child of type %s" | 441 | "Test OBJ to see if it a list of objects which are a child of type %s" |
| @@ -505,7 +448,10 @@ See `defclass' for more information." | |||
| 505 | (setq ans (and (eieio-object-p (car obj)) | 448 | (setq ans (and (eieio-object-p (car obj)) |
| 506 | (object-of-class-p (car obj) ,cname))) | 449 | (object-of-class-p (car obj) ,cname))) |
| 507 | (setq obj (cdr obj))) | 450 | (setq obj (cdr obj))) |
| 508 | ans)))))) | 451 | ans)))) |
| 452 | (make-obsolete csym (format "use (cl-typep ... '(list-of %s)) instead" | ||
| 453 | cname) | ||
| 454 | "25.1"))) | ||
| 509 | 455 | ||
| 510 | ;; Before adding new slots, let's add all the methods and classes | 456 | ;; Before adding new slots, let's add all the methods and classes |
| 511 | ;; in from the parent class. | 457 | ;; in from the parent class. |
| @@ -519,19 +465,13 @@ See `defclass' for more information." | |||
| 519 | 465 | ||
| 520 | ;; Query each slot in the declaration list and mangle into the | 466 | ;; Query each slot in the declaration list and mangle into the |
| 521 | ;; class structure I have defined. | 467 | ;; class structure I have defined. |
| 522 | (while slots | 468 | (pcase-dolist (`(,name . ,slot) slots) |
| 523 | (let* ((slot1 (car slots)) | 469 | (let* ((init (or (plist-get slot :initform) |
| 524 | (name (car slot1)) | ||
| 525 | (slot (cdr slot1)) | ||
| 526 | (acces (plist-get slot :accessor)) | ||
| 527 | (init (or (plist-get slot :initform) | ||
| 528 | (if (member :initform slot) nil | 470 | (if (member :initform slot) nil |
| 529 | eieio-unbound))) | 471 | eieio-unbound))) |
| 530 | (initarg (plist-get slot :initarg)) | 472 | (initarg (plist-get slot :initarg)) |
| 531 | (docstr (plist-get slot :documentation)) | 473 | (docstr (plist-get slot :documentation)) |
| 532 | (prot (plist-get slot :protection)) | 474 | (prot (plist-get slot :protection)) |
| 533 | (reader (plist-get slot :reader)) | ||
| 534 | (writer (plist-get slot :writer)) | ||
| 535 | (alloc (plist-get slot :allocation)) | 475 | (alloc (plist-get slot :allocation)) |
| 536 | (type (plist-get slot :type)) | 476 | (type (plist-get slot :type)) |
| 537 | (custom (plist-get slot :custom)) | 477 | (custom (plist-get slot :custom)) |
| @@ -542,51 +482,24 @@ See `defclass' for more information." | |||
| 542 | (skip-nil (eieio--class-option-assoc options :allow-nil-initform)) | 482 | (skip-nil (eieio--class-option-assoc options :allow-nil-initform)) |
| 543 | ) | 483 | ) |
| 544 | 484 | ||
| 545 | (if eieio-error-unsupported-class-tags | ||
| 546 | (let ((tmp slot)) | ||
| 547 | (while tmp | ||
| 548 | (if (not (member (car tmp) '(:accessor | ||
| 549 | :initform | ||
| 550 | :initarg | ||
| 551 | :documentation | ||
| 552 | :protection | ||
| 553 | :reader | ||
| 554 | :writer | ||
| 555 | :allocation | ||
| 556 | :type | ||
| 557 | :custom | ||
| 558 | :label | ||
| 559 | :group | ||
| 560 | :printer | ||
| 561 | :allow-nil-initform | ||
| 562 | :custom-groups))) | ||
| 563 | (signal 'invalid-slot-type (list (car tmp)))) | ||
| 564 | (setq tmp (cdr (cdr tmp)))))) | ||
| 565 | |||
| 566 | ;; Clean up the meaning of protection. | 485 | ;; Clean up the meaning of protection. |
| 567 | (cond ((or (eq prot 'public) (eq prot :public)) (setq prot nil)) | 486 | (setq prot |
| 568 | ((or (eq prot 'protected) (eq prot :protected)) (setq prot 'protected)) | 487 | (pcase prot |
| 569 | ((or (eq prot 'private) (eq prot :private)) (setq prot 'private)) | 488 | ((or 'nil 'public ':public) nil) |
| 570 | ((eq prot nil) nil) | 489 | ((or 'protected ':protected) 'protected) |
| 571 | (t (signal 'invalid-slot-type (list :protection prot)))) | 490 | ((or 'private ':private) 'private) |
| 572 | 491 | (_ (signal 'invalid-slot-type (list :protection prot))))) | |
| 573 | ;; Make sure the :allocation parameter has a valid value. | ||
| 574 | (if (not (or (not alloc) (eq alloc :class) (eq alloc :instance))) | ||
| 575 | (signal 'invalid-slot-type (list :allocation alloc))) | ||
| 576 | 492 | ||
| 577 | ;; The default type specifier is supposed to be t, meaning anything. | 493 | ;; The default type specifier is supposed to be t, meaning anything. |
| 578 | (if (not type) (setq type t)) | 494 | (if (not type) (setq type t)) |
| 579 | 495 | ||
| 580 | ;; Label is nil, or a string | ||
| 581 | (if (not (or (null label) (stringp label))) | ||
| 582 | (signal 'invalid-slot-type (list :label label))) | ||
| 583 | |||
| 584 | ;; Is there an initarg, but allocation of class? | ||
| 585 | (if (and initarg (eq alloc :class)) | ||
| 586 | (message "Class allocated slots do not need :initarg")) | ||
| 587 | |||
| 588 | ;; intern the symbol so we can use it blankly | 496 | ;; intern the symbol so we can use it blankly |
| 589 | (if initarg (set initarg initarg)) | 497 | (if eieio-backward-compatibility |
| 498 | (and initarg (not (keywordp initarg)) | ||
| 499 | (progn | ||
| 500 | (set initarg initarg) | ||
| 501 | (make-obsolete-variable | ||
| 502 | initarg (format "use '%s instead" initarg) "25.1")))) | ||
| 590 | 503 | ||
| 591 | ;; The customgroup should be a list of symbols | 504 | ;; The customgroup should be a list of symbols |
| 592 | (cond ((null customg) | 505 | (cond ((null customg) |
| @@ -604,63 +517,9 @@ See `defclass' for more information." | |||
| 604 | prot initarg alloc 'defaultoverride skip-nil) | 517 | prot initarg alloc 'defaultoverride skip-nil) |
| 605 | 518 | ||
| 606 | ;; We need to id the group, and store them in a group list attribute. | 519 | ;; We need to id the group, and store them in a group list attribute. |
| 607 | (mapc (lambda (cg) (cl-pushnew cg groups :test 'equal)) customg) | 520 | (dolist (cg customg) |
| 608 | 521 | (cl-pushnew cg groups :test 'equal)) | |
| 609 | ;; Anyone can have an accessor function. This creates a function | 522 | )) |
| 610 | ;; of the specified name, and also performs a `defsetf' if applicable | ||
| 611 | ;; so that users can `setf' the space returned by this function. | ||
| 612 | (if acces | ||
| 613 | (progn | ||
| 614 | (eieio--defmethod | ||
| 615 | acces (if (eq alloc :class) :static :primary) cname | ||
| 616 | `(lambda (this) | ||
| 617 | ,(format | ||
| 618 | "Retrieves the slot `%s' from an object of class `%s'" | ||
| 619 | name cname) | ||
| 620 | (if (slot-boundp this ',name) | ||
| 621 | ;; Use oref-default for :class allocated slots, since | ||
| 622 | ;; these also accept the use of a class argument instead | ||
| 623 | ;; of an object argument. | ||
| 624 | (,(if (eq alloc :class) 'eieio-oref-default 'eieio-oref) | ||
| 625 | this ',name) | ||
| 626 | ;; Else - Some error? nil? | ||
| 627 | nil))) | ||
| 628 | |||
| 629 | ;; FIXME: We should move more of eieio-defclass into the | ||
| 630 | ;; defclass macro so we don't have to use `eval' and require | ||
| 631 | ;; `gv' at run-time. | ||
| 632 | ;; FIXME: The defmethod above only defines a part of the generic | ||
| 633 | ;; function, but the define-setter below affects the whole | ||
| 634 | ;; generic function! | ||
| 635 | (eval `(gv-define-setter ,acces (eieio--store eieio--object) | ||
| 636 | ;; Apparently, eieio-oset-default doesn't work like | ||
| 637 | ;; oref-default and only accept class arguments! | ||
| 638 | (list ',(if nil ;; (eq alloc :class) | ||
| 639 | 'eieio-oset-default | ||
| 640 | 'eieio-oset) | ||
| 641 | eieio--object '',name | ||
| 642 | eieio--store))))) | ||
| 643 | |||
| 644 | ;; If a writer is defined, then create a generic method of that | ||
| 645 | ;; name whose purpose is to set the value of the slot. | ||
| 646 | (if writer | ||
| 647 | (eieio--defmethod | ||
| 648 | writer nil cname | ||
| 649 | `(lambda (this value) | ||
| 650 | ,(format "Set the slot `%s' of an object of class `%s'" | ||
| 651 | name cname) | ||
| 652 | (setf (slot-value this ',name) value)))) | ||
| 653 | ;; If a reader is defined, then create a generic method | ||
| 654 | ;; of that name whose purpose is to access this slot value. | ||
| 655 | (if reader | ||
| 656 | (eieio--defmethod | ||
| 657 | reader nil cname | ||
| 658 | `(lambda (this) | ||
| 659 | ,(format "Access the slot `%s' from object of class `%s'" | ||
| 660 | name cname) | ||
| 661 | (slot-value this ',name)))) | ||
| 662 | ) | ||
| 663 | (setq slots (cdr slots))) | ||
| 664 | 523 | ||
| 665 | ;; Now that everything has been loaded up, all our lists are backwards! | 524 | ;; Now that everything has been loaded up, all our lists are backwards! |
| 666 | ;; Fix that up now. | 525 | ;; Fix that up now. |
| @@ -700,30 +559,6 @@ See `defclass' for more information." | |||
| 700 | prots (cdr prots))) | 559 | prots (cdr prots))) |
| 701 | (setf (eieio--class-symbol-hashtable newc) oa)) | 560 | (setf (eieio--class-symbol-hashtable newc) oa)) |
| 702 | 561 | ||
| 703 | ;; Create the constructor function | ||
| 704 | (if (eieio--class-option-assoc options :abstract) | ||
| 705 | ;; Abstract classes cannot be instantiated. Say so. | ||
| 706 | (let ((abs (eieio--class-option-assoc options :abstract))) | ||
| 707 | (if (not (stringp abs)) | ||
| 708 | (setq abs (format "Class %s is abstract" cname))) | ||
| 709 | (fset cname | ||
| 710 | `(lambda (&rest stuff) | ||
| 711 | ,(format "You cannot create a new object of type %s" cname) | ||
| 712 | (error ,abs)))) | ||
| 713 | |||
| 714 | ;; Non-abstract classes need a constructor. | ||
| 715 | (fset cname | ||
| 716 | `(lambda (&rest slots) | ||
| 717 | ,(format "Create a new object with name NAME of class type %s" cname) | ||
| 718 | (if (and slots | ||
| 719 | (let ((x (car slots))) | ||
| 720 | (or (stringp x) (null x)))) | ||
| 721 | (funcall (if eieio-backward-compatibility #'ignore #'message) | ||
| 722 | "Obsolete name %S passed to %S constructor" | ||
| 723 | (pop slots) ',cname)) | ||
| 724 | (apply #'eieio-constructor ',cname slots))) | ||
| 725 | ) | ||
| 726 | |||
| 727 | ;; Set up a specialized doc string. | 562 | ;; Set up a specialized doc string. |
| 728 | ;; Use stored value since it is calculated in a non-trivial way | 563 | ;; Use stored value since it is calculated in a non-trivial way |
| 729 | (put cname 'variable-documentation | 564 | (put cname 'variable-documentation |
| @@ -1468,6 +1303,13 @@ method invocation orders of the involved classes." | |||
| 1468 | (define-error 'unbound-slot "Unbound slot") | 1303 | (define-error 'unbound-slot "Unbound slot") |
| 1469 | (define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") | 1304 | (define-error 'inconsistent-class-hierarchy "Inconsistent class hierarchy") |
| 1470 | 1305 | ||
| 1306 | ;;; Backward compatibility functions | ||
| 1307 | ;; To support .elc files compiled for older versions of EIEIO. | ||
| 1308 | |||
| 1309 | (defun eieio-defclass (cname superclasses slots options) | ||
| 1310 | (eval `(defclass ,cname ,superclasses ,slots ,options))) | ||
| 1311 | |||
| 1312 | |||
| 1471 | (provide 'eieio-core) | 1313 | (provide 'eieio-core) |
| 1472 | 1314 | ||
| 1473 | ;;; eieio-core.el ends here | 1315 | ;;; eieio-core.el ends here |
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el index 60bbd503adf..13ad120a9b5 100644 --- a/lisp/emacs-lisp/eieio-opt.el +++ b/lisp/emacs-lisp/eieio-opt.el | |||
| @@ -230,7 +230,7 @@ Optional argument CLASS is the class to start with. | |||
| 230 | If INSTANTIABLE-ONLY is non nil, only allow names of classes which | 230 | If INSTANTIABLE-ONLY is non nil, only allow names of classes which |
| 231 | are not abstract, otherwise allow all classes. | 231 | are not abstract, otherwise allow all classes. |
| 232 | Optional argument BUILDLIST is more list to attach and is used internally." | 232 | Optional argument BUILDLIST is more list to attach and is used internally." |
| 233 | (let* ((cc (or class eieio-default-superclass)) | 233 | (let* ((cc (or class 'eieio-default-superclass)) |
| 234 | (sublst (eieio--class-children (eieio--class-v cc)))) | 234 | (sublst (eieio--class-children (eieio--class-v cc)))) |
| 235 | (unless (assoc (symbol-name cc) buildlist) | 235 | (unless (assoc (symbol-name cc) buildlist) |
| 236 | (when (or (not instantiable-only) (not (class-abstract-p cc))) | 236 | (when (or (not instantiable-only) (not (class-abstract-p cc))) |
| @@ -561,7 +561,7 @@ current expansion depth." | |||
| 561 | (when (eq (point-min) (point-max)) | 561 | (when (eq (point-min) (point-max)) |
| 562 | ;; This function is only called once, to start the whole deal. | 562 | ;; This function is only called once, to start the whole deal. |
| 563 | ;; Create and expand the default object. | 563 | ;; Create and expand the default object. |
| 564 | (eieio-class-button eieio-default-superclass 0) | 564 | (eieio-class-button 'eieio-default-superclass 0) |
| 565 | (forward-line -1) | 565 | (forward-line -1) |
| 566 | (speedbar-expand-line))) | 566 | (speedbar-expand-line))) |
| 567 | 567 | ||
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index bf51986b133..205f13108b8 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el | |||
| @@ -58,13 +58,11 @@ | |||
| 58 | 58 | ||
| 59 | ;;; Defining a new class | 59 | ;;; Defining a new class |
| 60 | ;; | 60 | ;; |
| 61 | (defmacro defclass (name superclass slots &rest options-and-doc) | 61 | (defmacro defclass (name superclasses slots &rest options-and-doc) |
| 62 | "Define NAME as a new class derived from SUPERCLASS with SLOTS. | 62 | "Define NAME as a new class derived from SUPERCLASS with SLOTS. |
| 63 | OPTIONS-AND-DOC is used as the class' options and base documentation. | 63 | OPTIONS-AND-DOC is used as the class' options and base documentation. |
| 64 | SUPERCLASS is a list of superclasses to inherit from, with SLOTS | 64 | SUPERCLASSES is a list of superclasses to inherit from, with SLOTS |
| 65 | being the slots residing in that class definition. NOTE: Currently | 65 | being the slots residing in that class definition. Supported tags are: |
| 66 | only one slot may exist in SUPERCLASS as multiple inheritance is not | ||
| 67 | yet supported. Supported tags are: | ||
| 68 | 66 | ||
| 69 | :initform - Initializing form. | 67 | :initform - Initializing form. |
| 70 | :initarg - Tag used during initialization. | 68 | :initarg - Tag used during initialization. |
| @@ -115,12 +113,178 @@ Options in CLOS not supported in EIEIO: | |||
| 115 | Due to the way class options are set up, you can add any tags you wish, | 113 | Due to the way class options are set up, you can add any tags you wish, |
| 116 | and reference them using the function `class-option'." | 114 | and reference them using the function `class-option'." |
| 117 | (declare (doc-string 4)) | 115 | (declare (doc-string 4)) |
| 118 | ;; This is eval-and-compile only to silence spurious compiler warnings | 116 | (eieio--check-type listp superclasses) |
| 119 | ;; about functions and variables not known to be defined. | 117 | |
| 120 | ;; When eieio-defclass code is merged here and this becomes | 118 | (cond ((and (stringp (car options-and-doc)) |
| 121 | ;; transparent to the compiler, the eval-and-compile can be removed. | 119 | (/= 1 (% (length options-and-doc) 2))) |
| 122 | `(eval-and-compile | 120 | (error "Too many arguments to `defclass'")) |
| 123 | (eieio-defclass ',name ',superclass ',slots ',options-and-doc))) | 121 | ((and (symbolp (car options-and-doc)) |
| 122 | (/= 0 (% (length options-and-doc) 2))) | ||
| 123 | (error "Too many arguments to `defclass'"))) | ||
| 124 | |||
| 125 | (if (stringp (car options-and-doc)) | ||
| 126 | (setq options-and-doc | ||
| 127 | (cons :documentation options-and-doc))) | ||
| 128 | |||
| 129 | ;; Make sure the method invocation order is a valid value. | ||
| 130 | (let ((io (eieio--class-option-assoc options-and-doc | ||
| 131 | :method-invocation-order))) | ||
| 132 | (when (and io (not (member io '(:depth-first :breadth-first :c3)))) | ||
| 133 | (error "Method invocation order %s is not allowed" io))) | ||
| 134 | |||
| 135 | (let ((testsym1 (intern (concat (symbol-name name) "-p"))) | ||
| 136 | (testsym2 (intern (format "eieio--childp--%s" name))) | ||
| 137 | (accessors ())) | ||
| 138 | |||
| 139 | ;; Collect the accessors we need to define. | ||
| 140 | (pcase-dolist (`(,sname . ,soptions) slots) | ||
| 141 | (let* ((acces (plist-get soptions :accessor)) | ||
| 142 | (initarg (plist-get soptions :initarg)) | ||
| 143 | (reader (plist-get soptions :reader)) | ||
| 144 | (writer (plist-get soptions :writer)) | ||
| 145 | (alloc (plist-get soptions :allocation)) | ||
| 146 | (label (plist-get soptions :label))) | ||
| 147 | |||
| 148 | (if eieio-error-unsupported-class-tags | ||
| 149 | (let ((tmp soptions)) | ||
| 150 | (while tmp | ||
| 151 | (if (not (member (car tmp) '(:accessor | ||
| 152 | :initform | ||
| 153 | :initarg | ||
| 154 | :documentation | ||
| 155 | :protection | ||
| 156 | :reader | ||
| 157 | :writer | ||
| 158 | :allocation | ||
| 159 | :type | ||
| 160 | :custom | ||
| 161 | :label | ||
| 162 | :group | ||
| 163 | :printer | ||
| 164 | :allow-nil-initform | ||
| 165 | :custom-groups))) | ||
| 166 | (signal 'invalid-slot-type (list (car tmp)))) | ||
| 167 | (setq tmp (cdr (cdr tmp)))))) | ||
| 168 | |||
| 169 | ;; Make sure the :allocation parameter has a valid value. | ||
| 170 | (if (not (memq alloc '(nil :class :instance))) | ||
| 171 | (signal 'invalid-slot-type (list :allocation alloc))) | ||
| 172 | |||
| 173 | ;; Label is nil, or a string | ||
| 174 | (if (not (or (null label) (stringp label))) | ||
| 175 | (signal 'invalid-slot-type (list :label label))) | ||
| 176 | |||
| 177 | ;; Is there an initarg, but allocation of class? | ||
| 178 | (if (and initarg (eq alloc :class)) | ||
| 179 | (message "Class allocated slots do not need :initarg")) | ||
| 180 | |||
| 181 | ;; Anyone can have an accessor function. This creates a function | ||
| 182 | ;; of the specified name, and also performs a `defsetf' if applicable | ||
| 183 | ;; so that users can `setf' the space returned by this function. | ||
| 184 | (when acces | ||
| 185 | ;; FIXME: The defmethod below only defines a part of the generic | ||
| 186 | ;; function (good), but the define-setter below affects the whole | ||
| 187 | ;; generic function (bad)! | ||
| 188 | (push `(gv-define-setter ,acces (store object) | ||
| 189 | ;; Apparently, eieio-oset-default doesn't work like | ||
| 190 | ;; oref-default and only accept class arguments! | ||
| 191 | (list ',(if nil ;; (eq alloc :class) | ||
| 192 | 'eieio-oset-default | ||
| 193 | 'eieio-oset) | ||
| 194 | object '',sname store)) | ||
| 195 | accessors) | ||
| 196 | (push `(defmethod ,acces ,(if (eq alloc :class) :static :primary) | ||
| 197 | ((this ,name)) | ||
| 198 | ,(format | ||
| 199 | "Retrieve the slot `%S' from an object of class `%S'." | ||
| 200 | sname name) | ||
| 201 | (if (slot-boundp this ',sname) | ||
| 202 | ;; Use oref-default for :class allocated slots, since | ||
| 203 | ;; these also accept the use of a class argument instead | ||
| 204 | ;; of an object argument. | ||
| 205 | (,(if (eq alloc :class) 'eieio-oref-default 'eieio-oref) | ||
| 206 | this ',sname) | ||
| 207 | ;; Else - Some error? nil? | ||
| 208 | nil)) | ||
| 209 | accessors)) | ||
| 210 | |||
| 211 | ;; If a writer is defined, then create a generic method of that | ||
| 212 | ;; name whose purpose is to set the value of the slot. | ||
| 213 | (if writer | ||
| 214 | (push `(defmethod ,writer ((this ,name) value) | ||
| 215 | ,(format "Set the slot `%S' of an object of class `%S'." | ||
| 216 | sname name) | ||
| 217 | (setf (slot-value this ',sname) value)) | ||
| 218 | accessors)) | ||
| 219 | ;; If a reader is defined, then create a generic method | ||
| 220 | ;; of that name whose purpose is to access this slot value. | ||
| 221 | (if reader | ||
| 222 | (push `(defmethod ,reader ((this ,name)) | ||
| 223 | ,(format "Access the slot `%S' from object of class `%S'." | ||
| 224 | sname name) | ||
| 225 | (slot-value this ',sname)) | ||
| 226 | accessors)) | ||
| 227 | )) | ||
| 228 | |||
| 229 | `(progn | ||
| 230 | ;; This test must be created right away so we can have self- | ||
| 231 | ;; referencing classes. ei, a class whose slot can contain only | ||
| 232 | ;; pointers to itself. | ||
| 233 | |||
| 234 | ;; Create the test function. | ||
| 235 | (defun ,testsym1 (obj) | ||
| 236 | ,(format "Test OBJ to see if it an object of type %S." name) | ||
| 237 | (and (eieio-object-p obj) | ||
| 238 | (same-class-p obj ',name))) | ||
| 239 | |||
| 240 | (defun ,testsym2 (obj) | ||
| 241 | ,(format | ||
| 242 | "Test OBJ to see if it an object is a child of type %S." | ||
| 243 | name) | ||
| 244 | (and (eieio-object-p obj) | ||
| 245 | (object-of-class-p obj ',name))) | ||
| 246 | |||
| 247 | ,@(when eieio-backward-compatibility | ||
| 248 | (let ((f (intern (format "%s-child-p" name)))) | ||
| 249 | `((defalias ',f ',testsym2) | ||
| 250 | (make-obsolete | ||
| 251 | ',f ,(format "use (cl-typep ... '%s) instead" name) "25.1")))) | ||
| 252 | |||
| 253 | ;; When using typep, (typep OBJ 'myclass) returns t for objects which | ||
| 254 | ;; are subclasses of myclass. For our predicates, however, it is | ||
| 255 | ;; important for EIEIO to be backwards compatible, where | ||
| 256 | ;; myobject-p, and myobject-child-p are different. | ||
| 257 | ;; "cl" uses this technique to specify symbols with specific typep | ||
| 258 | ;; test, so we can let typep have the CLOS documented behavior | ||
| 259 | ;; while keeping our above predicate clean. | ||
| 260 | |||
| 261 | (put ',name 'cl-deftype-satisfies #',testsym2) | ||
| 262 | |||
| 263 | (eieio-defclass-internal ',name ',superclasses ',slots ',options-and-doc) | ||
| 264 | |||
| 265 | ,@accessors | ||
| 266 | |||
| 267 | ;; Create the constructor function | ||
| 268 | ,(if (eieio--class-option-assoc options-and-doc :abstract) | ||
| 269 | ;; Abstract classes cannot be instantiated. Say so. | ||
| 270 | (let ((abs (eieio--class-option-assoc options-and-doc :abstract))) | ||
| 271 | (if (not (stringp abs)) | ||
| 272 | (setq abs (format "Class %s is abstract" name))) | ||
| 273 | `(defun ,name (&rest _) | ||
| 274 | ,(format "You cannot create a new object of type %S." name) | ||
| 275 | (error ,abs))) | ||
| 276 | |||
| 277 | ;; Non-abstract classes need a constructor. | ||
| 278 | `(defun ,name (&rest slots) | ||
| 279 | ,(format "Create a new object with name NAME of class type %S." | ||
| 280 | name) | ||
| 281 | (if (and slots | ||
| 282 | (let ((x (car slots))) | ||
| 283 | (or (stringp x) (null x)))) | ||
| 284 | (funcall (if eieio-backward-compatibility #'ignore #'message) | ||
| 285 | "Obsolete name %S passed to %S constructor" | ||
| 286 | (pop slots) ',name)) | ||
| 287 | (apply #'eieio-constructor ',name slots)))))) | ||
| 124 | 288 | ||
| 125 | 289 | ||
| 126 | ;;; CLOS style implementation of object creators. | 290 | ;;; CLOS style implementation of object creators. |