chiark / gitweb /
Updated for CMUCL 19a and glib-2.4
[clg] / glib / proxy.lisp
index 7831a7677276da190d50ddd4cbd6f8258deef554..fa1e518775409484238c1d6cabf68a629d18c7e8 100644 (file)
 ;; License along with this library; if not, write to the Free Software
 ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-;; $Id: proxy.lisp,v 1.7 2002-01-20 14:52:04 espen Exp $
+;; $Id: proxy.lisp,v 1.8 2004-10-27 14:59:00 espen Exp $
 
 (in-package "GLIB")
 
+(import 
+'(pcl::initialize-internal-slot-functions
+  pcl::compute-effective-slot-definition-initargs
+  pcl::compute-slot-accessor-info
+  pcl::reader-function pcl::writer-function pcl::boundp-function))
 
 ;;;; Superclass for all metaclasses implementing some sort of virtual slots
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
-  (defclass virtual-slot-class (pcl::standard-class))
+  (defclass virtual-slot-class (standard-class) 
+    ())
 
   (defclass direct-virtual-slot-definition (standard-direct-slot-definition)
     ((setter :reader slot-definition-setter :initarg :setter)
-     (getter :reader slot-definition-getter :initarg :getter)))
+     (getter :reader slot-definition-getter :initarg :getter)
+     (boundp :reader slot-definition-boundp :initarg :boundp)))
   
-  (defclass effective-virtual-slot-definition
-    (standard-effective-slot-definition)))
+  (defclass effective-virtual-slot-definition (standard-effective-slot-definition)
+    ((setter :reader slot-definition-setter :initarg :setter)
+     (getter :reader slot-definition-getter :initarg :getter)
+     (boundp :reader slot-definition-boundp :initarg :boundp)))
+
+  (defun most-specific-slot-value (instances slot &optional default)
+    (let ((object (find-if
+                  #'(lambda (ob)
+                      (and (slot-exists-p ob slot) (slot-boundp ob slot)))
+                  instances)))
+      (if object
+         (slot-value object slot)
+         default)))
+)
+
   
 
-(defmethod direct-slot-definition-class ((class virtual-slot-class) initargs)
+(defmethod direct-slot-definition-class ((class virtual-slot-class) &rest initargs)
   (if (eq (getf initargs :allocation) :virtual)
       (find-class 'direct-virtual-slot-definition)
     (call-next-method)))
 
-(defmethod effective-slot-definition-class ((class virtual-slot-class) initargs)
+(defmethod effective-slot-definition-class ((class virtual-slot-class) &rest initargs)
   (if (eq (getf initargs :allocation) :virtual)
       (find-class 'effective-virtual-slot-definition)
     (call-next-method)))
 
-(defun %most-specific-slot-value (slotds slot &optional default)
-  (let ((slotd
-        (find-if
-         #'(lambda (slotd)
-             (and
-              (slot-exists-p slotd slot)
-              (slot-boundp slotd slot)))
-         slotds)))
-    (if slotd
-       (slot-value slotd slot)
-      default)))
-(defgeneric compute-virtual-slot-accessors (class slotd direct-slotds))
-
-(defmethod compute-virtual-slot-accessors
-    ((class virtual-slot-class)
-     (slotd effective-virtual-slot-definition)
-     direct-slotds)
-    (let ((getter (%most-specific-slot-value direct-slotds 'getter))
-         (setter (%most-specific-slot-value direct-slotds 'setter)))
-      (list getter setter)))
-
-(defmethod compute-effective-slot-definition
-    ((class virtual-slot-class) direct-slotds)
-  (let ((slotd (call-next-method)))
-    (when (typep slotd 'effective-virtual-slot-definition)
-      (setf
-       (slot-value slotd 'pcl::location)
-       (compute-virtual-slot-accessors class slotd direct-slotds)))
-    slotd))
+
+(defmethod initialize-internal-slot-functions ((slotd effective-virtual-slot-definition))
+  (with-slots (getter setter boundp) slotd
+    (unless (slot-boundp slotd 'reader-function)
+      (setf 
+       (slot-value slotd 'reader-function)
+       (etypecase getter
+        (function getter)
+        (null #'(lambda (object)
+                  (declare (ignore object))
+                  (error "Can't read slot: ~A" (slot-definition-name slotd))))
+        (symbol #'(lambda (object)
+                    (funcall getter object))))))
+
+    (unless (slot-boundp slotd 'writer-function)
+      (setf 
+       (slot-value slotd 'writer-function)
+       (etypecase setter
+        (function setter)
+        (null #'(lambda (object)
+                  (declare (ignore object))
+                  (error "Can't set slot: ~A" (slot-definition-name slotd))))
+        ((or symbol cons) #'(lambda (value object)
+                              (funcall (fdefinition setter) value object))))))
+
+    (unless (slot-boundp slotd 'boundp-function)
+      (setf 
+       (slot-value slotd 'boundp-function)
+       (etypecase boundp
+        (function boundp)
+        (null #'(lambda (object)
+                  (declare (ignore object))
+                  t))
+        (symbol #'(lambda (object)
+                    (funcall boundp object)))))))
+  (initialize-internal-slot-gfs (slot-definition-name slotd)))
+
+
+
+(defmethod compute-slot-accessor-info ((slotd effective-virtual-slot-definition)
+                                           type gf)
+  nil)
+
+(defmethod compute-effective-slot-definition-initargs ((class virtual-slot-class) direct-slotds)
+  (if (eq (most-specific-slot-value direct-slotds 'allocation) :virtual)
+      (nconc 
+       (list :getter (most-specific-slot-value direct-slotds 'getter)
+            :setter (most-specific-slot-value direct-slotds 'setter)
+            :boundp (most-specific-slot-value direct-slotds 'boundp))
+       (call-next-method))
+    (call-next-method)))
+
 
 (defmethod slot-value-using-class
     ((class virtual-slot-class) (object standard-object)
      (slotd effective-virtual-slot-definition))
-  (let ((reader (first (slot-definition-location slotd))))
-    (if reader
-       (funcall reader object)
-      (slot-unbound class object (slot-definition-name slotd)))))
+  (if (funcall (slot-value slotd 'boundp-function) object)
+      (funcall (slot-value slotd 'reader-function) object)
+    (slot-unbound class object (slot-definition-name slotd))))
 
 (defmethod slot-boundp-using-class
     ((class virtual-slot-class) (object standard-object)
      (slotd effective-virtual-slot-definition))
-   (and (first (slot-definition-location slotd)) t))
-    
-(defmethod (setf slot-value-using-class)
+  (funcall (slot-value slotd 'boundp-function) object))
+  
+(defmethod (setf slot-value-using-class) 
     (value (class virtual-slot-class) (object standard-object)
      (slotd effective-virtual-slot-definition))
-  (let ((setter (second (slot-definition-location slotd))))
-    (cond
-     ((null setter)
-      (error
-       "Can't set read-only slot ~A in ~A"
-       (slot-definition-name slotd)
-       object))
-     ((or (functionp setter) (symbolp setter))
-      (funcall setter value object)
-      value)
-     (t
-      (funcall (fdefinition setter) value object)
-      value))))
-       
+  (funcall (slot-value slotd 'writer-function) value object))
+
+  
 (defmethod validate-superclass
-    ((class virtual-slot-class) (super pcl::standard-class))
+    ((class virtual-slot-class) (super standard-class))
   t)
 
 
@@ -159,15 +189,14 @@ (defmethod initialize-proxy ((instance proxy)
   (ext:finalize instance (instance-finalizer instance)))
 
 (defmethod instance-finalizer ((instance proxy))
-  (let ((free (proxy-class-free (class-of instance)))
+  (let ((class (class-of instance))
        (type (type-of instance))
        (location (proxy-location instance)))
-    (declare
-     (type symbol type)
-     (type system-area-pointer location))
-    #'(lambda ()
-       (funcall free type location)
-       (remove-cached-instance location))))
+    (declare (type symbol type) (type system-area-pointer location))
+    (let ((free (proxy-class-free class)))
+      #'(lambda ()
+         (funcall free type location)
+         (remove-cached-instance location)))))
 
 
 (deftype-method translate-type-spec proxy (type-spec)
@@ -188,15 +217,19 @@ (deftype-method translate-to-alien
     proxy (type-spec instance &optional weak-ref)
   (if weak-ref
       `(proxy-location ,instance)
-    `(funcall
-      ',(proxy-class-copy (find-class type-spec))
-      ',type-spec (proxy-location ,instance))))
+      (let ((copy (proxy-class-copy (find-class type-spec)))) 
+       (if (symbolp copy)
+           `(,copy ',type-spec (proxy-location ,instance))    
+       `(funcall ',copy ',type-spec (proxy-location ,instance))))))
 
 (deftype-method unreference-alien proxy (type-spec location)
-  `(funcall ',(proxy-class-free (find-class type-spec)) ',type-spec ,location))
+  (let ((free (proxy-class-free (find-class type-spec)))) 
+    (if (symbolp free)
+       `(,free ',type-spec ,location)
+    `(funcall ',free ',type-spec ,location))))
 
-(defun proxy-instance-size (proxy)
-  (proxy-class-size (class-of proxy)))
+;; (defun proxy-instance-size (proxy)
+;;   (proxy-class-size (class-of proxy)))
 
 ;;;; Metaclass used for subclasses of proxy
 
@@ -211,119 +244,145 @@   (defclass direct-alien-slot-definition (direct-virtual-slot-definition)
      (offset :reader slot-definition-offset :initarg :offset)))
   
   (defclass effective-alien-slot-definition (effective-virtual-slot-definition)
-    ((offset :reader slot-definition-offset)))
+    ((offset :reader slot-definition-offset :initarg :offset)))
   
-  (defclass effective-virtual-alien-slot-definition
-    (effective-virtual-slot-definition))
+  (defclass effective-virtual-alien-slot-definition (effective-virtual-slot-definition)
+    ())
 
 
   (defmethod most-specific-proxy-superclass ((class proxy-class))
     (find-if
      #'(lambda (class)
         (subtypep (class-name class) 'proxy))
-     (cdr (pcl::compute-class-precedence-list class))))
-
+     (cdr (compute-class-precedence-list class))))
+  
   (defmethod direct-proxy-superclass ((class proxy-class))
     (find-if
      #'(lambda (class)
         (subtypep (class-name class) 'proxy))
-     (pcl::class-direct-superclasses class)))
-
+     (class-direct-superclasses class)))
+  
   (defmethod shared-initialize ((class proxy-class) names
                                &rest initargs &key size copy free)
     (declare (ignore initargs))
     (call-next-method)
     (cond
-     (size (setf (slot-value class 'size) (first size)))
-     ((slot-boundp class 'size) (slot-makunbound class 'size)))
+      (size (setf (slot-value class 'size) (first size)))
+      ((slot-boundp class 'size) (slot-makunbound class 'size)))
     (cond
-     (copy (setf (slot-value class 'copy) (first copy)))
-     ((slot-boundp class 'copy) (slot-makunbound class 'copy)))
+      (copy (setf (slot-value class 'copy) (first copy)))
+      ((slot-boundp class 'copy) (slot-makunbound class 'copy)))
     (cond
-     (free (setf (slot-value class 'free) (first free)))
-     ((slot-boundp class 'free) (slot-makunbound class 'free))))
-
-  (defmethod finalize-inheritance ((class proxy-class))
-    (call-next-method)
+      (free (setf (slot-value class 'free) (first free)))
+      ((slot-boundp class 'free) (slot-makunbound class 'free))))
+  
+;;   (defmethod finalize-inheritance ((class proxy-class))
+;;     (call-next-method)
+  (defmethod shared-initialize :after ((class proxy-class) names &rest initargs)
     (let ((super (most-specific-proxy-superclass class)))
       (unless (or (not super) (eq super (find-class 'proxy)))
-       (unless (or (slot-boundp class 'copy) (not (slot-boundp super 'copy)))
-         (setf (slot-value class 'copy) (proxy-class-copy super)))
-       (unless (or (slot-boundp class 'free) (not (slot-boundp super 'free)))
-         (setf (slot-value class 'free) (proxy-class-free super))))))
-
-  (defmethod direct-slot-definition-class ((class proxy-class) initargs)
+       (unless (or (slot-boundp class 'copy) (not (slot-boundp super 'copy)))
+         (setf (slot-value class 'copy) (proxy-class-copy super)))
+       (unless (or (slot-boundp class 'free) (not (slot-boundp super 'free)))
+         (setf (slot-value class 'free) (proxy-class-free super))))))
+  
+  (defmethod direct-slot-definition-class ((class proxy-class) &rest initargs)
     (case (getf initargs :allocation)
       ((nil :alien) (find-class 'direct-alien-slot-definition))
-;      (:instance (error "Allocation :instance not allowed in class ~A" class))
       (t (call-next-method))))
-
-  (defmethod effective-slot-definition-class ((class proxy-class) initargs)
+  
+  (defmethod effective-slot-definition-class ((class proxy-class) &rest initargs)
     (case (getf initargs :allocation)
       (:alien (find-class 'effective-alien-slot-definition))
       (:virtual (find-class 'effective-virtual-alien-slot-definition))
       (t (call-next-method))))
   
-  (defmethod compute-virtual-slot-accessors
-      ((class proxy-class) (slotd effective-alien-slot-definition)
-       direct-slotds)
-    (with-slots (offset type) slotd
-      (let ((reader (intern-reader-function type))
-           (writer (intern-writer-function type))
-           (destroy (intern-destroy-function type)))
-       (setf offset (slot-definition-offset (first direct-slotds)))
-       (list
-        #'(lambda (object)
-            (funcall reader (proxy-location object) offset))
-        #'(lambda (value object)
-            (let ((location (proxy-location object)))
-              (funcall destroy location offset)
-              (funcall writer value location offset)))))))
-  (defmethod compute-virtual-slot-accessors
-      ((class proxy-class)
-       (slotd effective-virtual-alien-slot-definition)
-       direct-slotds)
-    (destructuring-bind (getter setter) (call-next-method)
-      (with-slots (type) slotd
-       (list
-        (if (stringp getter)
-            (let ((getter (mkbinding-late getter type 'pointer)))
-              #'(lambda (object)
-                  (funcall getter (proxy-location object))))
-          getter)
-        (if (stringp setter)
-            (let ((setter (mkbinding-late setter 'nil 'pointer type)))
-              #'(lambda (value object)
-                  (funcall setter (proxy-location object) value)))
-          setter)))))
+  
+  (defmethod compute-effective-slot-definition-initargs ((class proxy-class) direct-slotds)
+    (if (eq (most-specific-slot-value direct-slotds 'allocation) :alien)
+       (nconc 
+        (list :offset (most-specific-slot-value direct-slotds 'offset))
+        (call-next-method))
+      (call-next-method)))
+  
+
+  (defmethod initialize-internal-slot-functions ((slotd effective-alien-slot-definition))
+    (with-slots (offset) slotd
+      (let* ((type (slot-definition-type slotd))
+            (reader (intern-reader-function type))
+            (writer (intern-writer-function type))
+            (destroy (intern-destroy-function type)))
+       (unless (slot-boundp slotd 'reader-function)
+         (setf 
+          (slot-value slotd 'reader-function)
+          #'(lambda (object)
+              (funcall reader (proxy-location object) offset))))
+
+       (unless (slot-boundp slotd 'writer-function)
+         (setf 
+          (slot-value slotd 'writer-function)
+          #'(lambda (value object)
+              (let ((location (proxy-location object)))
+                (funcall destroy location offset)
+                (funcall writer value location offset)))))
+
+       (unless (slot-boundp slotd 'boundp-function)
+         (setf 
+          (slot-value slotd 'boundp-function)
+          #'(lambda (object)
+              (declare (ignore object))
+              t)))))
+    (call-next-method))
+  
+
+  (defmethod initialize-internal-slot-functions ((slotd effective-virtual-alien-slot-definition))
+    (with-slots (getter setter type) slotd
+      (when (and (not (slot-boundp slotd 'reader-function)) (stringp getter))
+       (let ((reader (mkbinding-late getter type 'pointer)))
+         (setf (slot-value slotd 'reader-function)
+               #'(lambda (object)
+                   (funcall reader (proxy-location object))))))
+      
+      (when (and (not (slot-boundp slotd 'writer-function)) (stringp setter))
+       (let ((writer (mkbinding-late setter 'nil 'pointer type)))
+         (setf (slot-value slotd 'writer-function)
+               #'(lambda (value object)
+                   (funcall writer (proxy-location object) value))))))
+    (call-next-method))
+
+  ;; TODO: call some C code to detect this a compile time
+  (defconstant +struct-alignmen+ 4)
 
   (defmethod compute-slots ((class proxy-class))
-    (with-slots (direct-slots size) class
-      (let ((current-offset
-            (proxy-class-size (most-specific-proxy-superclass class)))
-           (max-size 0))
-       (dolist (slotd direct-slots)
-         (when (eq (slot-definition-allocation slotd) :alien)
-           (with-slots (offset type) slotd
-             (unless (slot-boundp slotd 'offset)
-               (setf offset current-offset))
-             (setq current-offset (+ offset (size-of type)))
-             (setq max-size (max max-size current-offset)))))
-       (unless (slot-boundp class 'size)
-         (setf size max-size))))
+    ;; This stuff should really go somewhere else
+    (loop 
+     with offset = (proxy-class-size (most-specific-proxy-superclass class))
+     with size = offset
+     for slotd in (class-direct-slots class)
+     when (eq (slot-definition-allocation slotd) :alien)
+     do (if (not (slot-boundp slotd 'offset))
+           (setf (slot-value slotd 'offset) offset)
+         (setq offset (slot-value slotd 'offset)))
+
+        (incf offset (size-of (slot-definition-type slotd)))
+       (incf offset (mod offset +struct-alignmen+))
+       (setq size (max size offset))
+
+     finally (unless (slot-boundp class 'size)
+              (setf (slot-value class 'size) size)))
     (call-next-method))
-   
-  (defmethod validate-superclass ((class proxy-class)
-                                 (super pcl::standard-class))
-    (subtypep (class-name super) 'proxy))
 
+  
+  (defmethod validate-superclass ((class proxy-class) (super standard-class))
+    (subtypep (class-name super) 'proxy))
+  
   (defmethod proxy-class-size (class)
     (declare (ignore class))
     0)
-
-  (defgeneric make-proxy-instance (class location weak-ref
-                                  &rest initargs &key)))
+)
+  
+(defgeneric make-proxy-instance (class location weak-ref
+                                      &rest initargs &key));)
 
 (defmethod make-proxy-instance ((class symbol) location weak-ref
                                &rest initargs &key)
@@ -353,8 +412,7 @@   (defclass struct (proxy)
     (:copy %copy-struct)
     (:free %free-struct)))
 
-(defmethod initialize-instance ((structure struct)
-                               &rest initargs)
+(defmethod initialize-instance ((structure struct) &rest initargs)
   (declare (ignore initargs))
   (setf 
    (slot-value structure 'location)