Changeset 379
- Timestamp:
- Jan 24, 2004, 3:34:01 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/ccl/examples/objc-clos.lisp (modified) (21 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ccl/examples/objc-clos.lisp
r267 r379 16 16 ;;; 17 17 ;;; 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 19 21 ;;; - OBJC-FOREIGN-ARG-TYPE in BRIDGE.LISP needs to handle BITFIELDs, 20 22 ;;; ARRAYs and UNIONs … … 22 24 ;;; - Need to add getter and setter functions for more foriegn slot types 23 25 ;;; - Canonicalization and retention for ObjC objects 26 ;;; - Support redef of CLOS parts, but not changes in ObjC parts 24 27 ;;; - Provide Lisp structs for NS-POINT, NS-RECT, etc.? 25 28 … … 59 62 (init-objc-class-slot-definitions (pref c :objc_class.super_class)) 60 63 (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)) 62 65 (values))) 63 66 … … 84 87 (if (setq idx (objc-metaclass-id p)) 85 88 (%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)))))) 93 91 94 92 (defun %objc-domain-class-of (p) … … 292 290 293 291 (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)) 295 294 296 295 (defclass foreign-effective-slot-definition (effective-slot-definition) … … 299 298 300 299 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 302 302 303 303 (defmethod direct-slot-definition-class ((class objc:objc-class-object) 304 304 &rest initargs) 305 (if ( eq (getf initargs :allocation):foreign)305 (if (getf initargs :foreign) 306 306 (find-class 'foreign-direct-slot-definition) 307 307 (find-class 'standard-direct-slot-definition))) … … 309 309 (defmethod effective-slot-definition-class ((class objc:objc-class-object) 310 310 &rest initargs) 311 (if ( eq (getf initargs :allocation):foreign)311 (if (getf initargs :foreign) 312 312 (find-class 'foreign-effective-slot-definition) 313 313 (find-class 'standard-effective-slot-definition))) … … 330 330 when (eql (schar name 0) #\_) 331 331 do (unexport sym ns-package) 332 do (format t "~S: ~S~%" name (pref ivar :objc_ivar.ivar_offset)) 332 333 collect 333 334 (make-direct-slot-definition … … 335 336 (list 336 337 :name sym 337 :allocation :foreign 338 :allocation :instance 339 :foreign t 338 340 :class (find-class 'foreign-effective-slot-definition) 339 341 :type (objc-foreign-arg-type 340 342 (%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 343 372 344 373 ;;; 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)))) 345 382 346 383 (defun compute-foreign-slot-accessors (eslotd) … … 348 385 (flet ((unhandled-foreign-slot-type (ptr &optional offset) 349 386 (declare (ignore ptr offset)) 350 ( error "Unhandled foreign slot type: ~S"ftype)))387 (make-instance 'unhandled-foreign-slot :ftype ftype))) 351 388 (case ftype 352 389 (:unsigned-byte (values #'%get-unsigned-byte #'%set-byte)) … … 356 393 (:unsigned-fullword (values #'%get-unsigned-long #'%set-long)) 357 394 (: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)) 360 399 (:single-float (values #'%get-single-float #'%set-single-float)) 361 400 (:double-float (values #'%get-double-float #'%set-double-float)) … … 365 404 ((and (consp ftype) (eq (first ftype) :*)) 366 405 (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)))))))) 368 408 369 409 … … 374 414 name 375 415 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))) 382 431 (multiple-value-bind (getter setter) (compute-foreign-slot-accessors eslotd) 383 432 (setf (foreign-slot-definition-getter eslotd) getter) … … 388 437 ;;; Determine the location of each slot 389 438 390 (defun collect-slots-with-alloc (alloc slotds)391 (loop for slotd in slotds392 when (eq (%slot-definition-allocation slotd) alloc)393 collect slotd))394 395 439 (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)))) 412 465 413 466 … … 448 501 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 449 502 450 (defmethod make-instance ((class objc:objc-class ) &rest initargs)451 (let ((instance (a llocate-instance class)))503 (defmethod make-instance ((class objc:objc-class-object) &rest initargs) 504 (let ((instance (apply #'allocate-instance class initargs))) 452 505 (apply #'initialize-instance instance initargs) 453 506 instance)) … … 458 511 (let* ((instance (%send class 'alloc)) ; For now; Use SEND macro eventually 459 512 (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)))) 461 515 (setf (slot-vector.instance slot-vector) instance) 462 516 (setf (gethash instance *objc-object-slot-vectors*) slot-vector) … … 469 523 (apply #'shared-initialize instance nil initargs)) 470 524 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) 472 527 (let ((class (class-of instance))) 473 528 ;; Call appropriate ObjC init method … … 476 531 ;; Initialize CLOS slots 477 532 (dolist (slotd (class-slots class)) 478 (when (n eq (slot-definition-allocation slotd) :foreign); For now533 (when (not (typep slotd 'foreign-direct-slot-definition)) ; For now 479 534 (let ((sname (slot-definition-name slotd)) 480 535 (slot-type (slot-definition-type slotd)) … … 482 537 (initfunction (slot-definition-initfunction slotd))) 483 538 (multiple-value-bind (ignore newval foundp) 484 (get-properties initargs (slot-definition-initargs slotd)) 539 (get-properties initargs 540 (slot-definition-initargs slotd)) 485 541 (declare (ignore ignore)) 486 542 (if foundp … … 489 545 (report-bad-arg newval slot-type)) 490 546 (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)) 492 549 (eq curval (%slot-unbound-marker)) 493 550 initfunction) … … 501 558 ;;;; Class Definition and Finalization Protocols ;;;; 502 559 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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.
