X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Fstd-class.lisp;h=6b09912bbeeba15fdf28a4aba0542e04dc63146a;hb=3b6e07c0fcb050fa86c7c42db33f49107e3097e6;hp=3acc5db71b5d32d3ace15e3adcc618295abb0891;hpb=603af6830a9c242adcec3fe3549e74e04cbe3228;p=sbcl.git diff --git a/src/pcl/std-class.lisp b/src/pcl/std-class.lisp index 3acc5db..6b09912 100644 --- a/src/pcl/std-class.lisp +++ b/src/pcl/std-class.lisp @@ -286,13 +286,14 @@ (constantly (make-member-type :members (list (specializer-object specl)))))) (defun real-load-defclass (name metaclass-name supers slots other - readers writers slot-names source-location) + readers writers slot-names source-location safe-p) (with-single-package-locked-error (:symbol name "defining ~S as a class") (%compiler-defclass name readers writers slot-names) (let ((res (apply #'ensure-class name :metaclass metaclass-name :direct-superclasses supers :direct-slots slots :definition-source source-location + 'safe-p safe-p other))) res))) @@ -309,9 +310,7 @@ (defmethod ensure-class-using-class ((class null) name &rest args &key) (multiple-value-bind (meta initargs) - (ensure-class-values class args) - #+nil - (set-class-type-translation (class-prototype meta) name) + (frob-ensure-class-args args) (setf class (apply #'make-instance meta :name name initargs)) (without-package-locks (setf (find-class name) class)) @@ -320,7 +319,7 @@ (defmethod ensure-class-using-class ((class pcl-class) name &rest args &key) (multiple-value-bind (meta initargs) - (ensure-class-values class args) + (frob-ensure-class-args args) (unless (eq (class-of class) meta) (apply #'change-class class meta initargs)) (apply #'reinitialize-instance class initargs) @@ -329,34 +328,29 @@ (set-class-type-translation class name) class)) -(defun fix-super (s) - (cond ((classp s) s) - ((not (legal-class-name-p s)) - (error "~S is not a class or a legal class name." s)) - (t - (or (find-class s nil) - (ensure-class s :metaclass 'forward-referenced-class))))) - -(defun ensure-class-values (class initargs) +(defun frob-ensure-class-args (args) (let (metaclass metaclassp reversed-plist) - (doplist (key val) initargs - (cond ((eq key :metaclass) - (setf metaclass val - metaclassp key)) - (t - (when (eq key :direct-superclasses) - (setf val (mapcar #'fix-super val))) - (setf reversed-plist (list* val key reversed-plist))))) - (values (cond (metaclassp - (if (classp metaclass) - metaclass - (find-class metaclass))) - ((or (null class) (forward-referenced-class-p class)) - *the-class-standard-class*) - (t - (class-of class))) - (nreverse reversed-plist)))) - + (flet ((frob-superclass (s) + (cond + ((classp s) s) + ((legal-class-name-p s) + (or (find-class s nil) + (ensure-class s :metaclass 'forward-referenced-class))) + (t (error "Not a class or a legal class name: ~S." s))))) + (doplist (key val) args + (cond ((eq key :metaclass) + (unless metaclassp + (setf metaclass val metaclassp key))) + (t + (when (eq key :direct-superclasses) + (setf val (mapcar #'frob-superclass val))) + (setf reversed-plist (list* val key reversed-plist))))) + (values (cond (metaclassp + (if (classp metaclass) + metaclass + (find-class metaclass))) + (t *the-class-standard-class*)) + (nreverse reversed-plist))))) (defmethod shared-initialize :after ((class std-class) slot-names &key @@ -410,27 +404,10 @@ (push old collect))))) (nreverse collect))) (add-direct-subclasses class direct-superclasses) - (update-class class nil) - (do* ((slots (slot-value class 'slots) (cdr slots)) - (dupes nil)) - ((null slots) (when dupes - (style-warn - ;; FIXME: the indentation request ("~4I") - ;; below appears not to do anything. Finding - ;; out why would be nice. -- CSR, 2003-04-24 - "~@~@:>" - class - dupes))) - (let* ((slot (car slots)) - (oslots (remove (slot-definition-name slot) (cdr slots) - :test #'string/= :key #'slot-definition-name))) - (when oslots - (pushnew (cons (slot-definition-name slot) - (mapcar #'slot-definition-name oslots)) - dupes - :test #'string= :key #'car)))) + (if (class-finalized-p class) + ;; required by AMOP, "Reinitialization of Class Metaobjects" + (finalize-inheritance class) + (update-class class nil)) (add-slot-accessors class direct-slots) (make-preliminary-layout class)) @@ -462,7 +439,8 @@ (order-layout-inherits (map 'simple-vector #'class-wrapper (reverse (rest cpl)))))) - (register-layout layout :invalidate t)))) + (register-layout layout :invalidate t) + (set-class-type-translation class (layout-classoid layout))))) (mapc #'make-preliminary-layout (class-direct-subclasses class))))) @@ -639,7 +617,8 @@ (values defstruct-form constructor reader-names writer-names))) (defun make-defstruct-allocation-function (class) - (let ((dd (get-structure-dd (class-name class)))) + ;; FIXME: Why don't we go class->layout->info == dd + (let ((dd (find-defstruct-description (class-name class)))) (lambda () (sb-kernel::%make-instance-with-layout (sb-kernel::compiler-layout-or-lose (dd-name dd)))))) @@ -719,33 +698,30 @@ (fix-slot-accessors class dslotds 'remove)) (defun fix-slot-accessors (class dslotds add/remove) - (flet ((fix (gfspec name r/w) + (flet ((fix (gfspec name r/w doc) (let ((gf (cond ((eq add/remove 'add) - (if (fboundp gfspec) - (without-package-locks - (ensure-generic-function gfspec)) + (or (find-generic-function gfspec nil) (ensure-generic-function gfspec :lambda-list (case r/w (r '(object)) (w '(new-value object)))))) - ((generic-function-p (and (fboundp gfspec) - (fdefinition gfspec))) - (without-package-locks - (ensure-generic-function gfspec)))))) + (t + (find-generic-function gfspec nil))))) (when gf (case r/w (r (if (eq add/remove 'add) - (add-reader-method class gf name) + (add-reader-method class gf name doc) (remove-reader-method class gf))) (w (if (eq add/remove 'add) - (add-writer-method class gf name) + (add-writer-method class gf name doc) (remove-writer-method class gf)))))))) (dolist (dslotd dslotds) - (let ((slot-name (slot-definition-name dslotd))) + (let ((slot-name (slot-definition-name dslotd)) + (slot-doc (%slot-definition-documentation dslotd))) (dolist (r (slot-definition-readers dslotd)) - (fix r slot-name 'r)) + (fix r slot-name 'r slot-doc)) (dolist (w (slot-definition-writers dslotd)) - (fix w slot-name 'w)))))) + (fix w slot-name 'w slot-doc)))))) (defun add-direct-subclasses (class supers) (dolist (super supers) @@ -775,16 +751,16 @@ ;;; or reinitialized. The class may or may not be finalized. (defun update-class (class finalizep) (without-package-locks - (when (or finalizep (class-finalized-p class)) - (update-cpl class (compute-class-precedence-list class)) - ;; This invocation of UPDATE-SLOTS, in practice, finalizes the - ;; class. - (update-slots class (compute-slots class)) - (update-gfs-of-class class) - (update-initargs class (compute-default-initargs class)) - (update-ctors 'finalize-inheritance :class class)) - (dolist (sub (class-direct-subclasses class)) - (update-class sub nil)))) + (when (or finalizep (class-finalized-p class)) + (update-cpl class (compute-class-precedence-list class)) + ;; This invocation of UPDATE-SLOTS, in practice, finalizes the + ;; class. + (update-slots class (compute-slots class)) + (update-gfs-of-class class) + (update-initargs class (compute-default-initargs class)) + (update-ctors 'finalize-inheritance :class class)) + (dolist (sub (class-direct-subclasses class)) + (update-class sub nil)))) (define-condition cpl-protocol-violation (reference-condition error) ((class :initarg :class :reader cpl-protocol-violation-class) @@ -881,7 +857,25 @@ (wrapper-instance-slots-layout nwrapper) nlayout (wrapper-class-slots nwrapper) nwrapper-class-slots (wrapper-no-of-instance-slots nwrapper) nslots - wrapper nwrapper)) + wrapper nwrapper) + (do* ((slots (slot-value class 'slots) (cdr slots)) + (dupes nil)) + ((null slots) + (when dupes + (style-warn + "~@~@:>" + class dupes))) + (let* ((slot (car slots)) + (oslots (remove (slot-definition-name slot) (cdr slots) + :test #'string/= + :key #'slot-definition-name))) + (when oslots + (pushnew (cons (slot-definition-name slot) + (mapcar #'slot-definition-name oslots)) + dupes + :test #'string= :key #'car))))) (setf (slot-value class 'finalized-p) t) (unless (eq owrapper nwrapper) (update-pv-table-cache-info class) @@ -1045,6 +1039,7 @@ (allocation nil) (allocation-class nil) (type t) + (type-check-function nil) (documentation nil) (documentationp nil) (namep nil) @@ -1070,6 +1065,15 @@ allocation-class (slot-definition-class slotd) allocp t)) (setq initargs (append (slot-definition-initargs slotd) initargs)) + (let ((fun (slot-definition-type-check-function slotd))) + (when fun + (setf type-check-function + (if type-check-function + (let ((old-function type-check-function)) + (lambda (value) + (funcall old-function value) + (funcall fun value))) + fun)))) (let ((slotd-type (slot-definition-type slotd))) (setq type (cond ((eq type t) slotd-type) @@ -1086,6 +1090,7 @@ :allocation allocation :allocation-class allocation-class :type type + 'type-check-function type-check-function :class class :documentation documentation))) @@ -1107,38 +1112,43 @@ (declare (ignore direct-slot initargs)) (find-class 'standard-reader-method)) -(defmethod add-reader-method ((class slot-class) generic-function slot-name) +(defmethod add-reader-method ((class slot-class) generic-function slot-name slot-documentation) (add-method generic-function (make-a-method 'standard-reader-method () (list (or (class-name class) 'object)) (list class) (make-reader-method-function class slot-name) - "automatically generated reader method" - slot-name))) + (or slot-documentation "automatically generated reader method") + :slot-name slot-name + :object-class class + :method-class-function #'reader-method-class))) (defmethod writer-method-class ((class slot-class) direct-slot &rest initargs) (declare (ignore direct-slot initargs)) (find-class 'standard-writer-method)) -(defmethod add-writer-method ((class slot-class) generic-function slot-name) +(defmethod add-writer-method ((class slot-class) generic-function slot-name slot-documentation) (add-method generic-function (make-a-method 'standard-writer-method () (list 'new-value (or (class-name class) 'object)) (list *the-class-t* class) (make-writer-method-function class slot-name) - "automatically generated writer method" - slot-name))) + (or slot-documentation "automatically generated writer method") + :slot-name slot-name + :object-class class + :method-class-function #'writer-method-class))) -(defmethod add-boundp-method ((class slot-class) generic-function slot-name) +(defmethod add-boundp-method ((class slot-class) generic-function slot-name slot-documentation) (add-method generic-function - (make-a-method 'standard-boundp-method + (make-a-method (constantly (find-class 'standard-boundp-method)) + class () (list (or (class-name class) 'object)) (list class) (make-boundp-method-function class slot-name) - "automatically generated boundp method" + (or slot-documentation "automatically generated boundp method") slot-name))) (defmethod remove-reader-method ((class slot-class) generic-function) @@ -1154,9 +1164,10 @@ (let ((method (get-method generic-function () (list class) nil))) (when method (remove-method generic-function method)))) -;;; MAKE-READER-METHOD-FUNCTION and MAKE-WRITE-METHOD function are NOT -;;; part of the standard protocol. They are however useful, PCL makes -;;; use of them internally and documents them for PCL users. +;;; MAKE-READER-METHOD-FUNCTION and MAKE-WRITER-METHOD-FUNCTION +;;; function are NOT part of the standard protocol. They are however +;;; useful; PCL makes use of them internally and documents them for +;;; PCL users. (FIXME: but SBCL certainly doesn't) ;;; ;;; *** This needs work to make type testing by the writer functions which ;;; *** do type testing faster. The idea would be to have one constructor @@ -1168,13 +1179,13 @@ ;;; *** defined for this metaclass a chance to run. (defmethod make-reader-method-function ((class slot-class) slot-name) - (make-std-reader-method-function (class-name class) slot-name)) + (make-std-reader-method-function class slot-name)) (defmethod make-writer-method-function ((class slot-class) slot-name) - (make-std-writer-method-function (class-name class) slot-name)) + (make-std-writer-method-function class slot-name)) (defmethod make-boundp-method-function ((class slot-class) slot-name) - (make-std-boundp-method-function (class-name class) slot-name)) + (make-std-boundp-method-function class slot-name)) (defmethod compatible-meta-class-change-p (class proto-new-class) (eq (class-of class) (class-of proto-new-class))) @@ -1510,7 +1521,11 @@ ;; FILE-STREAM and STRING-STREAM (as they have the same ;; layout-depthoid). Is there any way we can provide a useful ;; error message? -- CSR, 2005-05-03 - (eq s *the-class-file-stream*) (eq s *the-class-string-stream*))) + (eq s *the-class-file-stream*) (eq s *the-class-string-stream*) + ;; This probably shouldn't be mixed in with certain other + ;; classes, too, but it seems to work both with STANDARD-OBJECT + ;; and FUNCALLABLE-STANDARD-OBJECT + (eq s *the-class-sequence*))) ;;; Some necessary methods for FORWARD-REFERENCED-CLASS (defmethod class-direct-slots ((class forward-referenced-class)) ())