[rjain-utils-cvs] CVS prototypes
rjain
rjain at common-lisp.net
Tue Nov 24 10:36:44 UTC 2009
Update of /project/rjain-utils/cvsroot/prototypes
In directory cl-net:/tmp/cvs-serv6722
Modified Files:
prototypes.lisp
Log Message:
add delegation and all slot operations
add tests
--- /project/rjain-utils/cvsroot/prototypes/prototypes.lisp 2009/11/24 10:30:48 1.1.1.1
+++ /project/rjain-utils/cvsroot/prototypes/prototypes.lisp 2009/11/24 10:36:43 1.2
@@ -1,5 +1,5 @@
(defpackage :prototypes
- (:use :cl :sb-mop))
+ (:use :cl #+sbcl :sb-mop #-sbcl :mop))
(in-package :prototypes)
@@ -9,24 +9,85 @@
(defmethod validate-superclass ((proto prototype-class) (super standard-class))
t)
-(defclass prototype-instance (standard-object)
- ()
+(defclass prototype-object ()
+ ((delegate :initarg :delegate :reader prototype-delegate :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)))
-(defmethod slot-missing (class (object prototype-instance) slot-name (operation (eql 'setf)) &optional new-value)
+(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)
- (make-instance 'prototype-class
- :direct-superclasses (list class)
- :direct-slots (list (make-instance 'standard-direct-slot-definition :name slot-name :initarg slot-name))))))
- (change-class object slot-name new-class new-value)))
-
-(defmethod make-instance ((prototype prototype-instance) &key)
- (apply #'make-instance (class-of prototype)
- (mapcan (lambda (slot) (let ((name (slot-definition-name slot)))
- (when (slot-boundp prototype name)
- (list name (slot-value prototype name)))))
- (class-slots (class-of prototype)))))
+ (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)))
+
+(defmethod make-instance ((prototype prototype-object) &key)
+ (make-instance 'prototype-object :delegate prototype))
+
+
+;;;; TESTS
+
+(defparameter *1* (make-instance 'prototype-object))
+
+(setf (slot-value *1* 'x) 1)
+
+(defparameter *2* (make-instance *1*))
+
+(assert (eql (slot-value *2* 'x) 1))
+
+(defparameter *3* (make-instance *2*))
+
+(assert (eql (slot-value *3* 'x) 1))
+
+(defparameter *3.1* (make-instance *2*))
+
+(assert (eql (slot-value *3.1* 'x) 1))
+
+(setf (slot-value *2* 'x) 2)
+
+(assert (eql (slot-value *2* 'x) 2))
+
+(assert (eql (slot-value *3* 'x) 2))
+
+(assert (eql (slot-value *3.1* 'x) 2))
+
+(setf (slot-value *3* 'x) 3)
+
+(assert (eql (slot-value *2* 'x) 2))
+
+(assert (eql (slot-value *3* 'x) 3))
+
+(assert (eql (slot-value *3.1* 'x) 2))
More information about the Rjain-utils-cvs
mailing list