Changeset 379


Ignore:
Timestamp:
Jan 24, 2004, 3:34:01 PM (21 years ago)
Author:
Gary Byers
Message:

Lots of changes from Randall Beer.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/ccl/examples/objc-clos.lisp

    r267 r379  
    1616;;;
    1717;;; TO DO
    18 ;;;  - Write SHARED-INITIALIZE and FINALIZE-INHERITANCE for ObjC classes
     18;;;  - Issues with OFFSET/LOCATION in foreign direct and effective slot definitions
     19;;;  - MAP-OBJC-CLASS needs to INITIALIZE-INSTANCE and FINALIZE-INHERITANCE
     20;;;    for predefined classes
    1921;;;  - OBJC-FOREIGN-ARG-TYPE in BRIDGE.LISP needs to handle BITFIELDs,
    2022;;;    ARRAYs and UNIONs
     
    2224;;;  - Need to add getter and setter functions for more foriegn slot types
    2325;;;  - Canonicalization and retention for ObjC objects
     26;;;  - Support redef of CLOS parts, but not changes in ObjC parts
    2427;;;  - Provide Lisp structs for NS-POINT, NS-RECT, etc.?
    2528
     
    5962    (init-objc-class-slot-definitions (pref c :objc_class.super_class))
    6063    (setf (slot-value c 'direct-slots) (%compute-foreign-direct-slots c))
    61     (setf (slot-value c 'slots) (compute-slots c))
     64    (update-slots c (compute-slots c))
    6265    (values)))
    6366
     
    8487      (if (setq idx (objc-metaclass-id p))
    8588        (%set-macptr-type p (dpb objc-flag-metaclass objc-type-flags idx))
    86         (when #+apple-objc (not (%null-ptr-p (#_malloc_zone_from_ptr p)))
    87               #+gnu-objc t
    88               (with-macptrs ((parent (pref p
    89                                            #+apple-objc :objc_object.isa
    90                                            #+gnu-objc :objc_object.class_pointer)))
    91                 (if (setq idx (objc-class-id parent))
    92                   (%set-macptr-type p idx))))))))
     89        (if (setq idx (%objc-instance-class-index p))
     90          (%set-macptr-type p idx))))))
    9391
    9492(defun %objc-domain-class-of (p)
     
    292290
    293291(defclass foreign-direct-slot-definition (direct-slot-definition)
    294   ((offset :initarg :offset :reader foreign-slot-definition-offset)))
     292  ((foreign :initarg :foreign))
     293  (:default-initargs :type :id))
    295294
    296295(defclass foreign-effective-slot-definition (effective-slot-definition)
     
    299298
    300299
    301 ;;; Use the foreign slot metaclasses if the slot :ALLOCATION is :FOREIGN
     300;;; Use the foreign slot metaclasses if the slot has a :FOREIGN attribute
     301;;  of T
    302302
    303303(defmethod direct-slot-definition-class ((class objc:objc-class-object)
    304304                                         &rest initargs)
    305   (if (eq  (getf initargs :allocation) :foreign)
     305  (if (getf initargs :foreign)
    306306      (find-class 'foreign-direct-slot-definition)
    307307    (find-class 'standard-direct-slot-definition)))
     
    309309(defmethod effective-slot-definition-class ((class objc:objc-class-object)
    310310                                            &rest initargs)
    311   (if (eq (getf initargs :allocation) :foreign)
     311  (if (getf initargs :foreign)
    312312      (find-class 'foreign-effective-slot-definition)
    313313    (find-class 'standard-effective-slot-definition)))
     
    330330              when (eql (schar name 0) #\_)
    331331                do (unexport sym ns-package)
     332              do (format t "~S: ~S~%" name (pref ivar :objc_ivar.ivar_offset))
    332333              collect
    333334              (make-direct-slot-definition
     
    335336               (list
    336337                :name sym
    337                 :allocation :foreign
     338                :allocation :instance
     339                :foreign t
    338340                :class (find-class 'foreign-effective-slot-definition)
    339341                :type (objc-foreign-arg-type
    340342                       (%get-cstring (pref ivar :objc_ivar.ivar_type)))
    341                 :offset (pref ivar :objc_ivar.ivar_offset))))))))
    342          
     343;               :offset (pref ivar :objc_ivar.ivar_offset)
     344)))))))
     345       
     346
     347(defun %objc-ivar-offset-in-class (name c)
     348  ;; If C is a non-null ObjC class that contains an instance variable
     349  ;; named NAME, return that instance variable's offset,  else return
     350  ;; NIL.
     351  (when (objc-class-p c)
     352    (with-macptrs ((ivars (pref c :objc_class.ivars)))
     353      (unless (%null-ptr-p ivars)
     354        (loop with n = (pref ivars :objc_ivar_list.ivar_count)
     355              for i from 1 to n
     356              for ivar = (pref ivars :objc_ivar_list.ivar_list)
     357                  then (%inc-ptr ivar (record-length :objc_ivar))
     358              when (string= name (%get-cstring (pref ivar :objc_ivar.ivar_name)))
     359                do (return-from %objc-ivar-offset-in-class (pref ivar :objc_ivar.ivar_offset)))))))
     360
     361(defun %objc-ivar-offset (name c)
     362  (labels ((locate-objc-slot (name class)
     363             (unless (%null-ptr-p class)
     364                 (or (%objc-ivar-offset-in-class name class)
     365                     (with-macptrs ((super (pref class :objc_class.super_class)))
     366                       (unless (or (%null-ptr-p super) (eql super class))
     367                         (locate-objc-slot name super)))))))
     368    (when (objc-class-p c)
     369      (or (locate-objc-slot name c)
     370          (error "No ObjC instance variable named ~S in ~S" name c)))))
     371 
    343372
    344373;;; Return the getter and setter functions for a foreign slot
     374;;; NOTE: Should be changed to use FOREIGN-TYPE-TO-REPRESENTATION-TYPE
     375
     376(defclass unhandled-foreign-slot ()
     377    ((ftype :initarg :ftype :accessor unhandled-foreign-slot-ftype)))
     378
     379(defmethod print-object ((ufs unhandled-foreign-slot) stream)
     380  (print-unreadable-object (ufs stream :type t :identity t)
     381    (format stream "for foreign type ~s" (unhandled-foreign-slot-ftype ufs))))
    345382
    346383(defun compute-foreign-slot-accessors (eslotd)
     
    348385    (flet ((unhandled-foreign-slot-type (ptr &optional offset)
    349386             (declare (ignore ptr offset))
    350              (error "Unhandled foreign slot type: ~S" ftype)))
     387             (make-instance 'unhandled-foreign-slot :ftype ftype)))
    351388      (case ftype
    352389        (:unsigned-byte (values #'%get-unsigned-byte #'%set-byte))
     
    356393        (:unsigned-fullword (values #'%get-unsigned-long #'%set-long))
    357394        (:signed-fullword (values #'%get-signed-long #'%set-long))
    358         (:unsigned-longlong (values #'%%get-unsigned-longlong #'%%set-unsigned-longlong))
    359         (:signed-longlong (values #'%%get-signed-longlong #'%%set-signed-longlong))
     395        (:unsigned-longlong
     396         (values #'%%get-unsigned-longlong #'%%set-unsigned-longlong))
     397        (:signed-longlong
     398         (values #'%%get-signed-longlong #'%%set-signed-longlong))
    360399        (:single-float (values #'%get-single-float #'%set-single-float))
    361400        (:double-float (values #'%get-double-float #'%set-double-float))
     
    365404          ((and (consp ftype) (eq (first ftype) :*))
    366405           (values #'%get-ptr #'%set-ptr))
    367           (t (values #'unhandled-foreign-slot-type #'unhandled-foreign-slot-type))))))))
     406          (t (values #'unhandled-foreign-slot-type
     407                     #'unhandled-foreign-slot-type))))))))
    368408
    369409
     
    374414                                                      name
    375415                                                      direct-slots)
    376   (declare (ignore name))
    377   (let ((first (first direct-slots))
    378         (eslotd (call-next-method)))
    379     (when (typep eslotd 'foreign-effective-slot-definition)
    380       (setf (slot-value eslotd 'location)
    381             (foreign-slot-definition-offset first))
     416  (let* ((first (first direct-slots))
     417         (eslotd (call-next-method)))
     418    (when (typep first 'foreign-direct-slot-definition)
     419      (setq eslotd
     420            (make-effective-slot-definition
     421             class
     422             :name name
     423             :allocation (%slot-definition-allocation eslotd)
     424             :foreign t
     425             :documentation (%slot-definition-documentation eslotd)
     426             :class (%slot-definition-class first)
     427             :initargs (%slot-definition-initargs eslotd)
     428             :initfunction (%slot-definition-initfunction eslotd)
     429             :initform (%slot-definition-initform eslotd)
     430             :type (%slot-definition-type eslotd)))
    382431      (multiple-value-bind (getter setter) (compute-foreign-slot-accessors eslotd)
    383432        (setf (foreign-slot-definition-getter eslotd) getter)
     
    388437;;; Determine the location of each slot
    389438
    390 (defun collect-slots-with-alloc (alloc slotds)
    391   (loop for slotd in slotds
    392         when (eq (%slot-definition-allocation slotd) alloc)
    393          collect slotd))
    394 
    395439(defmethod compute-slots :around ((class objc:objc-class-object))
    396   (let* ((cpl (%class-precedence-list class))
    397          (slots (call-next-method))
    398          (instance-slots (collect-slots-with-alloc :instance slots))
    399          (class-slots (collect-slots-with-alloc :class slots))
    400          (foreign-slots (collect-slots-with-alloc :foreign slots)))
    401     (setq instance-slots
    402           (sort-effective-instance-slotds instance-slots class cpl))
    403     (loop for islot in instance-slots
    404           for loc = 1 then (1+ loc)
    405           do (setf (%slot-definition-location islot) loc))
    406     (dolist (cslot class-slots)
    407       (setf (%slot-definition-location cslot)
    408             (assoc (%slot-definition-name cslot)
    409                    (%class-get (%slot-definition-class cslot) :class-slots)
    410                    :test #'eq)))
    411      (append instance-slots class-slots foreign-slots)))
     440  (flet ((foreign-slot-p (s) (typep s 'foreign-effective-slot-definition)))
     441    (let* ((cpl (%class-precedence-list class))
     442           (slots (call-next-method))
     443           (instance-slots
     444            (remove-if #'foreign-slot-p
     445                       (remove :class slots :key #'%slot-definition-allocation)))
     446           (class-slots (remove :instance slots :key #'%slot-definition-allocation))
     447           (foreign-slots (remove-if-not #'foreign-slot-p slots)))
     448      (setq instance-slots
     449            (sort-effective-instance-slotds instance-slots class cpl))
     450      (format t "Instance slots: ~S~%Class Slots: ~S~%Foreign Slots: ~S~%"
     451              instance-slots class-slots foreign-slots)
     452      (loop for islot in instance-slots
     453            for loc = 1 then (1+ loc)
     454            do (setf (%slot-definition-location islot) loc))
     455      (dolist (cslot class-slots)
     456        (setf (%slot-definition-location cslot)
     457              (assoc (%slot-definition-name cslot)
     458                     (%class-get (%slot-definition-class cslot) :class-slots)
     459                     :test #'eq)))
     460      (dolist (fslot foreign-slots)
     461        (setf (%slot-definition-location fslot)
     462              (%objc-ivar-offset
     463               (compute-objc-variable-name (%slot-definition-name fslot)) class)))
     464      (append instance-slots class-slots foreign-slots))))
    412465
    413466
     
    448501;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    449502
    450 (defmethod make-instance ((class objc:objc-class) &rest initargs)
    451   (let ((instance (allocate-instance class)))
     503(defmethod make-instance ((class objc:objc-class-object) &rest initargs)
     504  (let ((instance (apply #'allocate-instance class initargs)))
    452505    (apply #'initialize-instance instance initargs)
    453506    instance))
     
    458511  (let* ((instance (%send class 'alloc)) ; For now; Use SEND macro eventually
    459512         (len (length (%wrapper-instance-slots (class-own-wrapper class))))
    460          (slot-vector (allocate-typed-vector :slot-vector (1+ len) (%slot-unbound-marker))))
     513         (slot-vector
     514          (allocate-typed-vector :slot-vector (1+ len) (%slot-unbound-marker))))
    461515    (setf (slot-vector.instance slot-vector) instance)
    462516    (setf (gethash instance *objc-object-slot-vectors*) slot-vector)
     
    469523  (apply #'shared-initialize instance nil initargs))
    470524
    471 (defmethod shared-initialize ((instance objc:objc-object) slot-names &rest initargs)
     525(defmethod shared-initialize ((instance objc:objc-object) slot-names
     526                              &rest initargs)
    472527  (let ((class (class-of instance)))
    473528    ;; Call appropriate ObjC init method
     
    476531    ;; Initialize CLOS slots
    477532    (dolist (slotd (class-slots class))
    478       (when (neq (slot-definition-allocation slotd) :foreign) ; For now
     533      (when (not (typep slotd 'foreign-direct-slot-definition)) ; For now
    479534        (let ((sname (slot-definition-name slotd))
    480535              (slot-type (slot-definition-type slotd))
     
    482537              (initfunction (slot-definition-initfunction slotd)))
    483538          (multiple-value-bind (ignore newval foundp)
    484                                (get-properties initargs (slot-definition-initargs slotd))
     539                               (get-properties initargs
     540                                               (slot-definition-initargs slotd))
    485541            (declare (ignore ignore))
    486542            (if foundp
     
    489545                  (report-bad-arg newval slot-type))
    490546              (let ((curval (slot-value instance sname)))
    491                 (when (and (or (eq slot-names t) (member sname slot-names :test #'eq))
     547                (when (and (or (eq slot-names t)
     548                               (member sname slot-names :test #'eq))
    492549                           (eq curval (%slot-unbound-marker))
    493550                           initfunction)
     
    501558;;;;              Class Definition and Finalization Protocols               ;;;;
    502559;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     560#|
     561(defclass demo-view (ns:ns-view)
     562  ((x :foreign t)
     563   y
     564   (r :foreign t :type :<NSR>ect))
     565  (:metaclass ns:+ns-object))
     566|#
     567
     568;;; Create the ObjC class/metaclass pair and dress it up in its minimal CLOS garb
     569;;; This currently requires that exactly one of DIRECT-SUPERCLASSES be a
     570;;; already existing subclass of OBJC:OBJC-CLASS
     571
     572(defun compute-objc-variable-name (sym)
     573  (let* ((pname (string sym))
     574         (first-alpha (position-if #'alpha-char-p pname)))
     575    (string-downcase
     576     (apply #'string-cat
     577            (mapcar #'string-capitalize (split-if-char #\- pname :elide)))
     578     :end (if first-alpha (1+ first-alpha) 1))))
     579
     580(defmethod allocate-instance ((metaclass objc:objc-metaclass)
     581                              &key name direct-superclasses direct-slots
     582                              &allow-other-keys)
     583  (let ((class-name (compute-objc-classname name))
     584        (superclass-name
     585         (loop for s in direct-superclasses
     586               when (typep s 'objc:objc-class)
     587                 collect s into objc-supers
     588               finally
     589               (if (= (length objc-supers) 1)
     590                   (return (compute-objc-classname (class-name (first objc-supers))))
     591                 (error "Exactly one OBJC:OBJC-CLASS must appear in ~S, found ~S"
     592                        direct-superclasses
     593                        (length objc-supers)))))
     594        (ivars
     595         (loop for splist in direct-slots
     596               when (getf splist :foreign)
     597                 collect (list (compute-objc-variable-name (getf splist :name))
     598                               (or (getf splist :type) :id)))))
     599    (%define-objc-class (note-objc-class class-name superclass-name ivars))))
     600
     601(defmethod shared-initialize ((class objc:objc-class) slot-names &rest initargs)
     602  ;; *** validate superclasses
     603  ;; *** create direct slot definition objects
     604  ;; *** dependency maintenance
     605  ;; *** maybe finalize inheritance
     606  class)
     607
     608(defmethod validate-superclass ((c1 objc:objc-class) (c2 objc:objc-class))
     609  t)
     610
     611(defmethod finalize-inheritance ((class objc:objc-class))
     612  ;; *** compute class precedence list
     613  ;; *** create effective slot definition objects
     614  )
     615
     616(defmethod make-instances-obsolete ((class objc:objc-class))
     617  ;; What should we do here?
     618  class)
     619
Note: See TracChangeset for help on using the changeset viewer.