(in-package "SB-PCL")
\f
-
;;; methods
;;;
;;; Methods themselves are simple inanimate objects. Most properties of
;;; methods are immutable, methods cannot be reinitialized. The following
;;; properties of methods can be changed:
;;; METHOD-GENERIC-FUNCTION
-;;; METHOD-FUNCTION ??
-
-(defmethod method-function ((method standard-method))
- (or (slot-value method '%function)
- (let ((fmf (slot-value method 'fast-function)))
- (unless fmf ; The :BEFORE SHARED-INITIALIZE method prevents this.
- (error "~S doesn't seem to have a METHOD-FUNCTION." method))
- (setf (slot-value method '%function)
- (method-function-from-fast-function fmf)))))
-
+\f
;;; initialization
;;;
;;; Error checking is done in before methods. Because of the simplicity of
(def update-instance-for-different-class ((old method) new &rest initargs)
"No behaviour specified for ~S on method objects."))
-(defmethod legal-documentation-p ((object standard-method) x)
- (if (or (null x) (stringp x))
- t
- "a string or NULL"))
-
-(defmethod legal-lambda-list-p ((object standard-method) x)
- (declare (ignore x))
- t)
+(define-condition invalid-method-initarg (simple-program-error)
+ ((method :initarg :method :reader invalid-method-initarg-method))
+ (:report
+ (lambda (c s)
+ (format s "~@<In initialization of ~S:~2I~_~?~@:>"
+ (invalid-method-initarg-method c)
+ (simple-condition-format-control c)
+ (simple-condition-format-arguments c)))))
+
+(defun invalid-method-initarg (method format-control &rest args)
+ (error 'invalid-method-initarg :method method
+ :format-control format-control :format-arguments args))
+
+(defun check-documentation (method doc)
+ (unless (or (null doc) (stringp doc))
+ (invalid-method-initarg method "~@<~S of ~S is neither ~S nor a ~S.~@:>"
+ :documentation doc 'null 'string)))
+(defun check-lambda-list (method ll)
+ nil)
-(defmethod legal-method-function-p ((object standard-method) x)
- (if (functionp x)
- t
- "a function"))
+(defun check-method-function (method fun)
+ (unless (functionp fun)
+ (invalid-method-initarg method "~@<~S of ~S is not a ~S.~@:>"
+ :function fun 'function)))
-(defmethod legal-qualifiers-p ((object standard-method) x)
+(defun check-qualifiers (method qualifiers)
(flet ((improper-list ()
- (return-from legal-qualifiers-p "Is not a proper list.")))
- (dolist-carefully (q x improper-list)
- (let ((ok (legal-qualifier-p object q)))
- (unless (eq ok t)
- (return-from legal-qualifiers-p
- (format nil "Contains ~S which ~A" q ok)))))
- t))
-
-(defmethod legal-qualifier-p ((object standard-method) x)
- (if (and x (atom x))
- t
- "is not a non-null atom"))
-
-(defmethod legal-slot-name-p ((object standard-method) x)
- (cond ((not (symbolp x)) "is not a symbol")
- (t t)))
-
-(defmethod legal-specializers-p ((object standard-method) x)
+ (invalid-method-initarg method
+ "~@<~S of ~S is an improper list.~@:>"
+ :qualifiers qualifiers)))
+ (dolist-carefully (q qualifiers improper-list)
+ (unless (and q (atom q))
+ (invalid-method-initarg method
+ "~@<~S, in ~S ~S, is not a non-~S atom.~@:>"
+ q :qualifiers qualifiers 'null)))))
+
+(defun check-slot-name (method name)
+ (unless (symbolp name)
+ (invalid-method-initarg "~@<~S of ~S is not a ~S.~@:>"
+ :slot-name name 'symbol)))
+
+(defun check-specializers (method specializers)
(flet ((improper-list ()
- (return-from legal-specializers-p "Is not a proper list.")))
- (dolist-carefully (s x improper-list)
- (let ((ok (legal-specializer-p object s)))
- (unless (eq ok t)
- (return-from legal-specializers-p
- (format nil "Contains ~S which ~A" s ok)))))
- t))
-
-(defvar *allow-experimental-specializers-p* nil)
-
-(defmethod legal-specializer-p ((object standard-method) x)
- (if (if *allow-experimental-specializers-p*
- (specializerp x)
- (or (classp x)
- (eql-specializer-p x)))
- t
- "is neither a class object nor an EQL specializer"))
-
-(defmethod shared-initialize :before ((method standard-method)
- slot-names
- &key qualifiers
- lambda-list
- specializers
- function
- fast-function
- documentation)
+ (invalid-method-initarg method
+ "~@<~S of ~S is an improper list.~@:>"
+ :specializers specializers)))
+ (dolist-carefully (s specializers improper-list)
+ (unless (specializerp s)
+ (invalid-method-initarg method
+ "~@<~S, in ~S ~S, is not a ~S.~@:>"
+ s :specializers specializers 'specializer)))
+ ;; KLUDGE: ANSI says that it's not valid to have methods
+ ;; specializing on classes which are "not defined", leaving
+ ;; unclear what the definedness of a class is; AMOP suggests that
+ ;; forward-referenced-classes, since they have proper names and
+ ;; all, are at least worthy of some level of definition. We allow
+ ;; methods specialized on forward-referenced-classes, but it's
+ ;; non-portable and potentially dubious, so
+ (let ((frcs (remove-if-not #'forward-referenced-class-p specializers)))
+ (unless (null frcs)
+ (style-warn "~@<Defining a method using ~
+ ~V[~;~1{~S~}~;~1{~S and ~S~}~:;~{~#[~;and ~]~S~^, ~}~] ~
+ as ~2:*~V[~;a specializer~:;specializers~].~@:>"
+ (length frcs) frcs)))))
+
+(defmethod shared-initialize :before
+ ((method standard-method) slot-names &key
+ qualifiers lambda-list specializers function documentation)
(declare (ignore slot-names))
- (flet ((lose (initarg value string)
- (error "when initializing the method ~S:~%~
- The ~S initialization argument was: ~S.~%~
- which ~A."
- method initarg value string)))
- (let ((check-qualifiers (legal-qualifiers-p method qualifiers))
- (check-lambda-list (legal-lambda-list-p method lambda-list))
- (check-specializers (legal-specializers-p method specializers))
- (check-fun (legal-method-function-p method
- (or function
- fast-function)))
- (check-documentation (legal-documentation-p method documentation)))
- (unless (eq check-qualifiers t)
- (lose :qualifiers qualifiers check-qualifiers))
- (unless (eq check-lambda-list t)
- (lose :lambda-list lambda-list check-lambda-list))
- (unless (eq check-specializers t)
- (lose :specializers specializers check-specializers))
- (unless (eq check-fun t)
- (lose :function function check-fun))
- (unless (eq check-documentation t)
- (lose :documentation documentation check-documentation)))))
-
-(defmethod shared-initialize :before ((method standard-accessor-method)
- slot-names
- &key slot-name slot-definition)
+ ;; FIXME: it's not clear to me (CSR, 2006-08-09) why methods get
+ ;; this extra paranoia and nothing else does; either everything
+ ;; should be aggressively checking initargs, or nothing much should.
+ ;; In either case, it would probably be better to have :type
+ ;; declarations in slots, which would then give a suitable type
+ ;; error (if we implement type-checking for slots...) rather than
+ ;; this hand-crafted thing.
+ (check-qualifiers method qualifiers)
+ (check-lambda-list method lambda-list)
+ (check-specializers method specializers)
+ (check-method-function method function)
+ (check-documentation method documentation))
+
+(defmethod shared-initialize :before
+ ((method standard-accessor-method) slot-names &key
+ slot-name slot-definition)
(declare (ignore slot-names))
(unless slot-definition
- (let ((legalp (legal-slot-name-p method slot-name)))
- ;; FIXME: nasty convention; should be renamed to ILLEGAL-SLOT-NAME-P and
- ;; ILLEGALP, and the convention redone to be less twisty
- (unless (eq legalp t)
- (error "The value of the :SLOT-NAME initarg ~A." legalp)))))
+ (check-slot-name method slot-name)))
(defmethod shared-initialize :after ((method standard-method) slot-names
- &rest initargs
- &key qualifiers method-spec plist)
- (declare (ignore slot-names method-spec plist))
- (initialize-method-function initargs nil method)
- (setf (plist-value method 'qualifiers) qualifiers)
- #+ignore
- (setf (slot-value method 'closure-generator)
- (method-function-closure-generator (slot-value method '%function))))
-
-(defmethod method-qualifiers ((method standard-method))
- (plist-value method 'qualifiers))
+ &rest initargs &key)
+ (declare (ignore slot-names))
+ (initialize-method-function initargs method))
+
\f
(defvar *the-class-generic-function*
(find-class 'generic-function))
(defmethod specializer-class ((specializer eql-specializer))
(class-of (slot-value specializer 'object)))
-(defvar *in-gf-arg-info-p* nil)
-(setf (gdefinition 'arg-info-reader)
- (let ((mf (initialize-method-function
- (make-internal-reader-method-function
- 'standard-generic-function 'arg-info)
- t)))
- (lambda (&rest args) (funcall mf args nil))))
-
-
(defun error-need-at-least-n-args (function n)
(error 'simple-program-error
:format-control "~@<The function ~2I~_~S ~I~_requires ~
(defun value-for-caching (gf classes)
(let ((methods (compute-applicable-methods-using-types
gf (mapcar #'class-eq-type classes))))
- (method-function-get (or (safe-method-fast-function (car methods))
- (safe-method-function (car methods)))
- :constant-value)))
+ (method-plist-value (car methods) :constant-value)))
(defun default-secondary-dispatch-function (generic-function)
(lambda (&rest args)
(unless *new-class*
(update-std-or-str-methods gf type))
(when (and (standard-svuc-method type) (structure-svuc-method type))
- (flet ((update-class (class)
+ (flet ((update-accessor-info (class)
(when (class-finalized-p class)
(dolist (slotd (class-slots class))
(compute-slot-accessor-info slotd type gf)))))
(if *new-class*
- (update-class *new-class*)
- (map-all-classes #'update-class 'slot-object)))))
+ (update-accessor-info *new-class*)
+ (map-all-classes #'update-accessor-info 'slot-object)))))
(defvar *standard-slot-value-using-class-method* nil)
(defvar *standard-setf-slot-value-using-class-method* nil)