]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/eieio-base.el
* lisp/emacs-lisp/eieio*.el: Use class objects in `parent' field.
[gnu-emacs] / lisp / emacs-lisp / eieio-base.el
index 211904466244fd09d0549684b7ad0e22c6450f00..7c0161b25d2a9b53c695a390355dd7b916602517 100644 (file)
@@ -1,6 +1,6 @@
-;;; eieio-base.el --- Base classes for EIEIO.
+;;; eieio-base.el --- Base classes for EIEIO.  -*- lexical-binding:t -*-
 
-;;; Copyright (C) 2000-2002, 2004-2005, 2007-2013 Free Software
+;;; Copyright (C) 2000-2002, 2004-2005, 2007-2014 Free Software
 ;;; Foundation, Inc.
 
 ;; Author: Eric M. Ludlam  <zappo@gnu.org>
@@ -31,7 +31,7 @@
 ;;; Code:
 
 (require 'eieio)
-(eval-when-compile (require 'cl))       ;FIXME: Use cl-lib!
+(eval-when-compile (require 'cl-lib))
 
 ;;; eieio-instance-inheritor
 ;;
@@ -52,7 +52,8 @@ a parent instance.  When a slot in the child is referenced, and has
 not been set, use values from the parent."
   :abstract t)
 
-(defmethod slot-unbound ((object eieio-instance-inheritor) class slot-name fn)
+(defmethod slot-unbound ((object eieio-instance-inheritor)
+                         _class slot-name _fn)
   "If a slot OBJECT in this CLASS is unbound, try to inherit, or throw a signal.
 SLOT-NAME is the offending slot.  FN is the function signaling the error."
   (if (slot-boundp object 'parent-instance)
@@ -62,25 +63,10 @@ SLOT-NAME is the offending slot.  FN is the function signaling the error."
     ;; Throw the regular signal.
     (call-next-method)))
 
-(defmethod clone ((obj eieio-instance-inheritor) &rest params)
+(defmethod clone ((obj eieio-instance-inheritor) &rest _params)
   "Clone OBJ, initializing `:parent' to OBJ.
 All slots are unbound, except those initialized with PARAMS."
-  (let ((nobj (make-vector (length obj) eieio-unbound))
-       (nm (eieio--object-name obj))
-       (passname (and params (stringp (car params))))
-       (num 1))
-    (aset nobj 0 'object)
-    (setf (eieio--object-class nobj) (eieio--object-class obj))
-    ;; The following was copied from the default clone.
-    (if (not passname)
-       (save-match-data
-         (if (string-match "-\\([0-9]+\\)" nm)
-             (setq num (1+ (string-to-number (match-string 1 nm)))
-                   nm (substring nm 0 (match-beginning 0))))
-         (setf (eieio--object-name nobj) (concat nm "-" (int-to-string num))))
-      (setf (eieio--object-name nobj) (car params)))
-    ;; Now initialize from params.
-    (if params (shared-initialize nobj (if passname (cdr params) params)))
+  (let ((nobj (call-next-method)))
     (oset nobj parent-instance obj)
     nobj))
 
@@ -118,7 +104,7 @@ a variable symbol used to store a list of all instances."
   :abstract t)
 
 (defmethod initialize-instance :AFTER ((this eieio-instance-tracker)
-                                      &rest slots)
+                                      &rest _slots)
   "Make sure THIS is in our master list of this class.
 Optional argument SLOTS are the initialization arguments."
   ;; Theoretically, this is never called twice for a given instance.
@@ -154,7 +140,7 @@ Multiple calls to `make-instance' will return this object."))
 A singleton is a class which will only ever have one instance."
   :abstract t)
 
-(defmethod constructor :STATIC ((class eieio-singleton) name &rest slots)
+(defmethod eieio-constructor :STATIC ((class eieio-singleton) &rest _slots)
   "Constructor for singleton CLASS.
 NAME and SLOTS initialize the new object.
 This constructor guarantees that no matter how many you request,
@@ -269,7 +255,7 @@ malicious code.
 Note: This function recurses when a slot of :type of some object is
 identified, and needing more object creation."
   (let ((objclass (nth 0 inputlist))
-       (objname (nth 1 inputlist))
+       ;; (objname (nth 1 inputlist))
        (slots (nthcdr 2 inputlist))
        (createslots nil))
 
@@ -284,7 +270,7 @@ identified, and needing more object creation."
        ;; In addition, strip out quotes, list functions, and update
        ;; object constructors as needed.
        (setq value (eieio-persistent-validate/fix-slot-value
-                    objclass name value))
+                    (eieio--class-v objclass) name value))
 
        (push name createslots)
        (push value createslots)
@@ -292,7 +278,7 @@ identified, and needing more object creation."
 
       (setq slots (cdr (cdr slots))))
 
-    (apply 'make-instance objclass objname (nreverse createslots))
+    (apply #'make-instance objclass (nreverse createslots))
 
     ;;(eval inputlist)
     ))
@@ -304,11 +290,13 @@ constructor functions are considered valid.
 Second, any text properties will be stripped from strings."
   (cond ((consp proposed-value)
         ;; Lists with something in them need special treatment.
-        (let ((slot-idx (eieio-slot-name-index class nil slot))
+        (let ((slot-idx (eieio--slot-name-index class
+                                                 nil slot))
               (type nil)
               (classtype nil))
-          (setq slot-idx (- slot-idx 3))
-          (setq type (aref (eieio--class-public-type (class-v class))
+          (setq slot-idx (- slot-idx
+                             (eval-when-compile eieio--object-num-slots)))
+          (setq type (aref (eieio--class-public-type class)
                            slot-idx))
 
           (setq classtype (eieio-persistent-slot-type-is-class-p
@@ -374,13 +362,13 @@ Second, any text properties will be stripped from strings."
   )
 
 (defun eieio-persistent-slot-type-is-class-p (type)
-  "Return the class refered to in TYPE.
+  "Return the class referred to in TYPE.
 If no class is referenced there, then return nil."
   (cond ((class-p type)
         ;; If the type is a class, then return it.
         type)
-
-       ((and (symbolp type) (string-match "-child$" (symbol-name type))
+        ;; FIXME: foo-child should not be a valid type!
+       ((and (symbolp type) (string-match "-child\\'" (symbol-name type))
              (class-p (intern-soft (substring (symbol-name type) 0
                                               (match-beginning 0)))))
         ;; If it is the predicate ending with -child, then return
@@ -388,8 +376,8 @@ If no class is referenced there, then return nil."
         ;; class is the same as if we used -child, so no further work needed.
         (intern-soft (substring (symbol-name type) 0
                                 (match-beginning 0))))
-
-       ((and (symbolp type) (string-match "-list$" (symbol-name type))
+        ;; FIXME: foo-list should not be a valid type!
+       ((and (symbolp type) (string-match "-list\\'" (symbol-name type))
              (class-p (intern-soft (substring (symbol-name type) 0
                                               (match-beginning 0)))))
         ;; If it is the predicate ending with -list, then return
@@ -462,34 +450,38 @@ instance."
 
 \f
 ;;; Named object
-;;
-;; Named objects use the objects `name' as a slot, and that slot
-;; is accessed with the `object-name' symbol.
 
 (defclass eieio-named ()
-  ()
-  "Object with a name.
-Name storage already occurs in an object.  This object provides get/set
-access to it."
+  ((object-name :initarg :object-name :initform nil))
+  "Object with a name."
   :abstract t)
 
-(defmethod slot-missing ((obj eieio-named)
-                        slot-name operation &optional new-value)
-  "Called when a non-existent slot is accessed.
-For variable `eieio-named', provide an imaginary `object-name' slot.
-Argument OBJ is the named object.
-Argument SLOT-NAME is the slot that was attempted to be accessed.
-OPERATION is the type of access, such as `oref' or `oset'.
-NEW-VALUE is the value that was being set into SLOT if OPERATION were
-a set type."
-  (if (memq slot-name '(object-name :object-name))
-      (cond ((eq operation 'oset)
-            (if (not (stringp new-value))
-                (signal 'invalid-slot-type
-                        (list obj slot-name 'string new-value)))
-            (eieio-object-set-name-string obj new-value))
-           (t (eieio-object-name-string obj)))
-    (call-next-method)))
+(defmethod eieio-object-name-string ((obj eieio-named))
+  "Return a string which is OBJ's name."
+  (or (slot-value obj 'object-name)
+      (symbol-name (eieio-object-class obj))))
+
+(defmethod eieio-object-set-name-string ((obj eieio-named) name)
+  "Set the string which is OBJ's NAME."
+  (eieio--check-type stringp name)
+  (eieio-oset obj 'object-name name))
+
+(defmethod clone ((obj eieio-named) &rest params)
+  "Clone OBJ, initializing `:parent' to OBJ.
+All slots are unbound, except those initialized with PARAMS."
+  (let* ((newname (and (stringp (car params)) (pop params)))
+         (nobj (apply #'call-next-method obj params))
+         (nm (slot-value obj 'object-name)))
+    (eieio-oset obj 'object-name
+                (or newname
+                    (save-match-data
+                      (if (and nm (string-match "-\\([0-9]+\\)" nm))
+                          (let ((num (1+ (string-to-number
+                                          (match-string 1 nm)))))
+                            (concat (substring nm 0 (match-beginning 0))
+                                    "-" (int-to-string num)))
+                        (concat nm "-1")))))
+    nobj))
 
 (provide 'eieio-base)