X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fpcl%2Fcombin.lisp;h=201620b089dad296681917eb86205d3e32adf10a;hb=1dc38285834db2d374a156a4f68b19096341deb3;hp=68f41004cede5cfe1b9294dc769007f29aeedbe2;hpb=665eea819b61f87f401ff0a9ff82f6cbdcc5c636;p=sbcl.git diff --git a/src/pcl/combin.lisp b/src/pcl/combin.lisp index 68f4100..201620b 100644 --- a/src/pcl/combin.lisp +++ b/src/pcl/combin.lisp @@ -31,18 +31,17 @@ (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))))))) @@ -83,7 +82,7 @@ (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)))) @@ -121,7 +120,7 @@ (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)) @@ -129,11 +128,15 @@ 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) @@ -150,31 +153,37 @@ :qualifiers nil ; XXX :function (method-call-function emf))) (fast-method-call - (make-instance 'standard-method - :specializers nil ; XXX - :qualifiers nil - :fast-function (fast-method-call-function emf))))) + (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 @@ -207,10 +216,9 @@ (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)))) @@ -224,8 +232,8 @@ (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)) @@ -234,23 +242,23 @@ (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)))))) @@ -301,7 +309,7 @@ (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)))) @@ -310,13 +318,14 @@ (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)))) @@ -410,7 +419,7 @@ (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)) @@ -479,34 +488,41 @@ (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 "~@= i more-count) + (when (and (invalid) (not allow-other-keys)) + (error 'simple-program-error + :format-control "~@" - :format-arguments (list (length (invalid)) (invalid) valid-keys))) - (return)) - (let ((key (pop args))) - (cond - ((not (symbolp key)) - (error 'simple-program-error - :format-control "~@" - :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 "~@" + :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)))))) ;;;; the STANDARD method combination type. This is coded by hand ;;;; (rather than with DEFINE-METHOD-COMBINATION) for bootstrapping