[rjain-utils-cvs] CVS prototypes

rjain rjain at common-lisp.net
Tue Nov 24 10:38:19 UTC 2009


Update of /project/rjain-utils/cvsroot/prototypes
In directory cl-net:/tmp/cvs-serv6830

Modified Files:
	prototypes.lisp 
Log Message:
add multiple delegation
macrolet for slot operation definition


--- /project/rjain-utils/cvsroot/prototypes/prototypes.lisp	2009/11/24 10:36:43	1.2
+++ /project/rjain-utils/cvsroot/prototypes/prototypes.lisp	2009/11/24 10:38:19	1.3
@@ -10,53 +10,52 @@
   t)
 
 (defclass prototype-object ()
-  ((delegate :initarg :delegate :reader prototype-delegate :initform nil))
+  ((delegates :initarg :delegates :reader prototype-delegates :initform nil))
   (:metaclass prototype-class))
 
 (defgeneric prototype-find-subclass (prototype slot-name))
 
 (defmethod prototype-find-subclass ((class prototype-class) slot-name)
-  (find-if (lambda (subclass) (eql slot-name (slot-definition-name (first (class-direct-slots subclass))))) 
-           (class-direct-subclasses class)))
+  (find slot-name
+        (class-direct-subclasses class)
+        :key (lambda (subclass) 
+               (slot-definition-name (first (class-direct-slots subclass))))))
 
 (defmethod prototype-find-subclass ((object prototype-object) slot-name)
   (prototype-find-subclass (class-of object) slot-name))
 
-(defmethod slot-missing (class (object prototype-object) slot-name
-                         (operation (eql 'slot-value))
-                         &optional new-value)
-  (if (null (prototype-delegate object))
-      (call-next-method)
-      (slot-value (prototype-delegate object) slot-name)))
-
-(defmethod slot-missing (class (object prototype-object) slot-name
-                         (operation (eql 'slot-boundp))
-                         &optional new-value)
-  (if (null (prototype-delegate object))
-      (call-next-method)
-      (slot-boundp (prototype-delegate object) slot-name)))
-
 (defun prototype-subclass (class slot-name)
   (make-instance 'prototype-class
                  :direct-superclasses (list class)
                  :direct-slots (list (list :name slot-name :initargs (list slot-name)))))
 
-(defmethod slot-missing (class (object prototype-object) slot-name
-                         (operation (eql 'setf)) &optional new-value)
-  (let ((new-class (or (prototype-find-subclass class slot-name)
-                       (prototype-subclass class slot-name))))
-    (change-class object new-class slot-name new-value)))
-
-(defmethod slot-missing (class (object prototype-object) slot-name
-                         (operation (eql 'slot-makunbound))
-                         &optional new-value)
-  (let ((new-class (or (prototype-find-subclass class slot-name)
-                       (prototype-subclass class slot-name))))
-    (change-class object new-class)))
+(defun ensure-subclass (class slot-name)
+  (or (prototype-find-subclass class slot-name)
+      (prototype-subclass class slot-name)))
+
+(macrolet ((reader-delegation (operation)
+             `(defmethod slot-missing (class (object prototype-object) slot-name
+                                       (operation (eql ',operation))
+                                       &optional new-value)
+                (declare (ignore new-value))
+                (dolist (delegate (prototype-delegates object)
+                         (call-next-method))
+                  (ignore-errors
+                    (return (,operation delegate slot-name)))))))
+  (reader-delegation slot-value)
+  (reader-delegation slot-boundp))
+
+(macrolet ((writer-subclassing (operation &rest initargs)
+           `(defmethod slot-missing (class (object prototype-object) slot-name
+                                     (operation (eql ',operation))
+                                     &optional new-value)
+              (let ((new-class (ensure-subclass class slot-name)))
+                (change-class object new-class , at initargs)))))
+  (writer-subclassing setf slot-name new-value)
+  (writer-subclassing slot-makunbound))
 
 (defmethod make-instance ((prototype prototype-object) &key)
-  (make-instance 'prototype-object :delegate prototype))
-
+  (make-instance 'prototype-object :delegates (list prototype)))
 
 ;;;; TESTS
 
@@ -91,3 +90,11 @@
 (assert (eql (slot-value *3* 'x) 3))
 
 (assert (eql (slot-value *3.1* 'x) 2))
+
+(slot-makunbound *3.1* 'x)
+
+(assert (eql (slot-value *2* 'x) 2))
+
+(assert (eql (slot-value *3* 'x) 3))
+
+(assert (not (slot-boundp *3.1* 'x)))





More information about the Rjain-utils-cvs mailing list