(if (listp method)
(early-method-function method)
(values nil (safe-method-fast-function method)))
- (let* ((pv-table (and fmf (method-function-pv-table fmf))))
+ (let* ((pv-table (and fmf (method-plist-value method :pv-table))))
(if (and fmf (or (null pv-table) wrappers))
(let* ((pv-wrappers (when pv-table
(pv-wrappers-from-all-wrappers
pv-table wrappers)))
- (pv-cell (when (and pv-table pv-wrappers)
- (pv-table-lookup pv-table pv-wrappers))))
- (values mf t fmf pv-cell))
+ (pv (when (and pv-table pv-wrappers)
+ (pv-table-lookup pv-table pv-wrappers))))
+ (values mf t fmf pv))
(values
(or mf (if (listp method)
- (setf (cadr method)
- (method-function-from-fast-function fmf))
+ (bug "early method with no method-function")
(method-function method)))
t nil nil)))))))
(early-method-function method)
(values nil (safe-method-fast-function method)))
(declare (ignore mf))
- (let* ((pv-table (and fmf (method-function-pv-table fmf))))
+ (let* ((pv-table (and fmf (method-plist-value method :pv-table))))
(if (and fmf (or (null pv-table) wrappers-p))
'fast-method-call
'method-call))))
;; or aren't to prevent the leaky next methods bug.
(let* ((cm-args (cdr form))
(fmf-p (and (null no-fmf-p)
- (or (not (eq *boot-state* 'complete))
+ (or (not (eq **boot-state** 'complete))
(gf-fast-method-function-p generic-function))
(null (cddr cm-args))))
(method (car cm-args))
(defun make-emf-from-method
(method cm-args &optional gf fmf-p method-alist wrappers)
- (multiple-value-bind (mf real-mf-p fmf pv-cell)
+ (multiple-value-bind (mf real-mf-p fmf pv)
(get-method-function method method-alist wrappers)
(if fmf
(let* ((next-methods (car cm-args))
gf (car next-methods)
(list* (cdr next-methods) (cdr cm-args))
fmf-p method-alist wrappers))
- (arg-info (method-function-get fmf :arg-info)))
- (make-fast-method-call :function fmf
- :pv-cell pv-cell
- :next-method-call next
- :arg-info arg-info))
+ (arg-info (method-plist-value method :arg-info))
+ (default (cons nil nil))
+ (value (method-plist-value method :constant-value default)))
+ (if (eq value default)
+ (make-fast-method-call :function fmf :pv pv
+ :next-method-call next :arg-info arg-info)
+ (make-constant-fast-method-call
+ :function fmf :pv pv :next-method-call next
+ :arg-info arg-info :value value)))
(if real-mf-p
(flet ((frob-cm-arg (arg)
(if (if (listp arg)
(method-p arg))
arg
(if (and (consp arg) (eq (car arg) 'make-method))
- (make-instance 'standard-method
- :specializers nil ; XXX
- :qualifiers nil
- :fast-function (fast-method-call-function
- (make-effective-method-function
- gf (cadr arg) method-alist wrappers)))
+ (let ((emf (make-effective-method-function
+ gf (cadr arg) method-alist wrappers)))
+ (etypecase emf
+ (method-call
+ (make-instance 'standard-method
+ :specializers nil ; XXX
+ :qualifiers nil ; XXX
+ :function (method-call-function emf)))
+ (fast-method-call
+ (let* ((fmf (fast-method-call-function emf))
+ (fun (method-function-from-fast-method-call emf))
+ (mf (%make-method-function fmf nil)))
+ (set-funcallable-instance-function mf fun)
+ (make-instance 'standard-method
+ :specializers nil ; XXX
+ :qualifiers nil
+ :function mf)))))
arg))))
- (make-method-call :function mf
- ;; FIXME: this is wrong. Very wrong.
- ;; It assumes that the only place that
- ;; can have make-method calls is in
- ;; the list structure of the second
- ;; argument to CALL-METHOD, but AMOP
- ;; says that CALL-METHOD can be more
- ;; complicated if
- ;; COMPUTE-EFFECTIVE-METHOD (and
- ;; presumably MAKE-METHOD-LAMBDA) is
- ;; adjusted to match.
- ;;
- ;; On the other hand, it's a start,
- ;; because without this calls to
- ;; MAKE-METHOD in method combination
- ;; where one of the methods is of a
- ;; user-defined class don't work at
- ;; all. -- CSR, 2006-08-05
- :call-method-args (cons (mapcar #'frob-cm-arg (car cm-args))
- (cdr cm-args))))
+ (let* ((default (cons nil nil))
+ (value
+ (method-plist-value method :constant-value default))
+ ;; FIXME: this is wrong. Very wrong. It assumes
+ ;; that the only place that can have make-method
+ ;; calls is in the list structure of the second
+ ;; argument to CALL-METHOD, but AMOP says that
+ ;; CALL-METHOD can be more complicated if
+ ;; COMPUTE-EFFECTIVE-METHOD (and presumably
+ ;; MAKE-METHOD-LAMBDA) is adjusted to match.
+ ;;
+ ;; On the other hand, it's a start, because
+ ;; without this calls to MAKE-METHOD in method
+ ;; combination where one of the methods is of a
+ ;; user-defined class don't work at all. -- CSR,
+ ;; 2006-08-05
+ (args (cons (mapcar #'frob-cm-arg (car cm-args))
+ (cdr cm-args))))
+ (if (eq value default)
+ (make-method-call :function mf :call-method-args args)
+ (make-constant-method-call :function mf :value value
+ :call-method-args args))))
mf))))
(defun make-effective-method-function-simple1
(defun expand-effective-method-function (gf effective-method &optional env)
(declare (ignore env))
- (multiple-value-bind (nreq applyp metatypes nkeys arg-info)
+ (multiple-value-bind (nreq applyp)
(get-generic-fun-info gf)
- (declare (ignore nreq nkeys arg-info))
- (let ((ll (make-fast-method-call-lambda-list metatypes applyp))
+ (let ((ll (make-fast-method-call-lambda-list nreq applyp))
(check-applicable-keywords
(when (and applyp (gf-requires-emf-keyword-checks gf))
'((check-applicable-keywords))))
(error-p (or (eq (first effective-method) '%no-primary-method)
(eq (first effective-method) '%invalid-qualifiers)))
(mc-args-p
- (when (eq *boot-state* 'complete)
+ (when (eq **boot-state** 'complete)
;; Otherwise the METHOD-COMBINATION slot is not bound.
(let ((combin (generic-function-method-combination gf)))
(and (long-method-combination-p combin)
(long-method-combination-args-lambda-list combin))))))
(cond
(error-p
- `(lambda (.pv-cell. .next-method-call. &rest .args.)
- (declare (ignore .pv-cell. .next-method-call.))
+ `(lambda (.pv. .next-method-call. &rest .args.)
+ (declare (ignore .pv. .next-method-call.))
(declare (ignorable .args.))
(flet ((%no-primary-method (gf args)
(apply #'no-primary-method gf args))
(declare (ignorable #'%no-primary-method #'%invalid-qualifiers))
,effective-method)))
(mc-args-p
- (let* ((required
- ;; FIXME: Ick. Shared idiom, too, with stuff in cache.lisp
- (let (req)
- (dotimes (i (length metatypes) (nreverse req))
- (push (dfun-arg-symbol i) req))))
+ (let* ((required (make-dfun-required-args nreq))
(gf-args (if applyp
- `(list* ,@required .dfun-rest-arg.)
+ `(list* ,@required
+ (sb-c::%listify-rest-args
+ .dfun-more-context.
+ (the (and unsigned-byte fixnum)
+ .dfun-more-count.)))
`(list ,@required))))
`(lambda ,ll
- (declare (ignore .pv-cell. .next-method-call.))
+ (declare (ignore .pv. .next-method-call.))
(let ((.gf-args. ,gf-args))
(declare (ignorable .gf-args.))
,@check-applicable-keywords
,effective-method))))
(t
`(lambda ,ll
- (declare (ignore ,@(if error-p ll '(.pv-cell. .next-method-call.))))
+ (declare (ignore ,@(if error-p ll '(.pv. .next-method-call.))))
,@check-applicable-keywords
,effective-method))))))
(call-method
(let ((gensym (get-effective-method-gensym)))
(values (make-emf-call
- metatypes applyp gensym
+ (length metatypes) applyp gensym
(make-effective-method-fun-type
generic-function form method-alist-p wrappers-p))
(list gensym))))
(type (make-effective-method-list-fun-type
generic-function form method-alist-p wrappers-p)))
(values `(dolist (emf ,gensym nil)
- ,(make-emf-call metatypes applyp 'emf type))
+ ,(make-emf-call (length metatypes) applyp 'emf type))
(list gensym))))
(check-applicable-keywords
- (values `(check-applicable-keywords
- .dfun-rest-arg. .keyargs-start. .valid-keys.)
+ (values `(check-applicable-keywords .keyargs-start.
+ .valid-keys.
+ .dfun-more-context.
+ .dfun-more-count.)
'(.keyargs-start. .valid-keys.)))
-
(t
(default-code-converter form))))
(dolist (m applicable-methods)
(let ((qualifiers (if (listp m)
(early-method-qualifiers m)
- (method-qualifiers m))))
+ (safe-method-qualifiers m))))
(cond
((null qualifiers) (primary m))
((cdr qualifiers) (invalid generic-function combin m))
(aver any-keyp)
(values (if allowp t keys) nopt)))))
-(defun check-applicable-keywords (args start valid-keys)
+(defun check-applicable-keywords (start valid-keys more-context more-count)
(let ((allow-other-keys-seen nil)
(allow-other-keys nil)
- (args (nthcdr start args)))
- (collect ((invalid))
- (loop
- (when (null args)
- (when (and (invalid) (not allow-other-keys))
- (error 'simple-program-error
- :format-control "~@<invalid keyword argument~P: ~
+ (i start))
+ (declare (type index i more-count)
+ (optimize speed))
+ (flet ((current-value ()
+ (sb-c::%more-arg more-context i)))
+ (declare (inline current-value))
+ (collect ((invalid))
+ (loop
+ (when (>= i more-count)
+ (when (and (invalid) (not allow-other-keys))
+ (error 'simple-program-error
+ :format-control "~@<invalid keyword argument~P: ~
~{~S~^, ~} (valid keys are ~{~S~^, ~}).~@:>"
- :format-arguments (list (length (invalid)) (invalid) valid-keys)))
- (return))
- (let ((key (pop args)))
- (cond
- ((not (symbolp key))
- (error 'simple-program-error
- :format-control "~@<keyword argument not a symbol: ~S.~@:>"
- :format-arguments (list key)))
- ((null args) (sb-c::%odd-key-args-error))
- ((eq key :allow-other-keys)
- ;; only the leftmost :ALLOW-OTHER-KEYS has any effect
- (unless allow-other-keys-seen
- (setq allow-other-keys-seen t
- allow-other-keys (car args))))
- ((eq t valid-keys))
- ((not (memq key valid-keys)) (invalid key))))
- (pop args)))))
+ :format-arguments (list (length (invalid)) (invalid) valid-keys)))
+ (return))
+ (let ((key (current-value)))
+ (incf i)
+ (cond
+ ((not (symbolp key))
+ (error 'simple-program-error
+ :format-control "~@<keyword argument not a symbol: ~S.~@:>"
+ :format-arguments (list key)))
+ ((= i more-count)
+ (sb-c::%odd-key-args-error))
+ ((eq key :allow-other-keys)
+ ;; only the leftmost :ALLOW-OTHER-KEYS has any effect
+ (unless allow-other-keys-seen
+ (setq allow-other-keys-seen t
+ allow-other-keys (current-value))))
+ ((eq t valid-keys))
+ ((not (memq key valid-keys)) (invalid key))))
+ (incf i))))))
\f
;;;; the STANDARD method combination type. This is coded by hand
;;;; (rather than with DEFINE-METHOD-COMBINATION) for bootstrapping