real-add-named-method)
))
-;;; For each of the early functions, arrange to have it point to its early
-;;; definition. Do this in a way that makes sure that if we redefine one
-;;; of the early definitions the redefinition will take effect. This makes
-;;; development easier.
+;;; For each of the early functions, arrange to have it point to its
+;;; early definition. Do this in a way that makes sure that if we
+;;; redefine one of the early definitions the redefinition will take
+;;; effect. This makes development easier.
;;;
-;;; The function which generates the redirection closure is pulled out into
-;;; a separate piece of code because of a bug in ExCL which causes this not
-;;; to work if it is inlined.
+;;; The function which generates the redirection closure is pulled out
+;;; into a separate piece of code because of a bug in ExCL which
+;;; causes this not to work if it is inlined.
;;; FIXME: We no longer need to worry about ExCL now, so we could unscrew this.
(eval-when (:load-toplevel :execute)
-(defun redirect-early-function-internal (real early)
+(defun !redirect-early-function-internal (real early)
(setf (gdefinition real)
(set-function-name
#'(lambda (&rest args)
(dolist (fns *!early-functions*)
(let ((name (car fns))
(early-name (cadr fns)))
- (redirect-early-function-internal name early-name)))
+ (!redirect-early-function-internal name early-name)))
) ; EVAL-WHEN
initargs))
\f
(defmacro defmethod (&rest args &environment env)
- (declare (arglist name
- {method-qualifier}*
- specialized-lambda-list
- &body body))
(multiple-value-bind (name qualifiers lambda-list body)
(parse-defmethod args)
(multiple-value-bind (proto-gf proto-method)
(extract-declarations body env)
(values `(lambda ,unspecialized-lambda-list
,@(when documentation `(,documentation))
- (declare (method-name ,(list name qualifiers specializers)))
- (declare (method-lambda-list ,@lambda-list))
+ (declare (%method-name ,(list name qualifiers specializers)))
+ (declare (%method-lambda-list ,@lambda-list))
,@declarations
,@real-body)
unspecialized-lambda-list specializers))))
(declare (ignore proto-gf proto-method))
(make-method-lambda-internal method-lambda env))
+;;; a helper function for creating Python-friendly type declarations
+;;; in DEFMETHOD forms
+(defun parameter-specializer-declaration-in-defmethod (parameter specializer)
+ (cond ((and (consp specializer)
+ (eq (car specializer) 'eql))
+ ;; KLUDGE: ANSI, in its wisdom, says that
+ ;; EQL-SPECIALIZER-FORMs in EQL specializers are evaluated at
+ ;; DEFMETHOD expansion time. Thus, although one might think
+ ;; that in
+ ;; (DEFMETHOD FOO ((X PACKAGE)
+ ;; (Y (EQL 12))
+ ;; ..))
+ ;; the PACKAGE and (EQL 12) forms are both parallel type
+ ;; names, they're not, as is made clear when you do
+ ;; (DEFMETHOD FOO ((X PACKAGE)
+ ;; (Y (EQL 'BAR)))
+ ;; ..)
+ ;; where Y needs to be a symbol named "BAR", not some cons
+ ;; made by (CONS 'QUOTE 'BAR). I.e. when the
+ ;; EQL-SPECIALIZER-FORM is (EQL 'X), it requires an argument
+ ;; to be of type (EQL X). It'd be easy to transform one to
+ ;; the other, but it'd be somewhat messier to do so while
+ ;; ensuring that the EQL-SPECIALIZER-FORM is only EVAL'd
+ ;; once. (The new code wouldn't be messy, but it'd require a
+ ;; big transformation of the old code.) So instead we punt.
+ ;; -- WHN 20000610
+ '(ignorable))
+ ((member specializer
+ ;; KLUDGE: For some low-level implementation
+ ;; classes, perhaps because of some problems related
+ ;; to the incomplete integration of PCL into SBCL's
+ ;; type system, some specializer classes can't be
+ ;; declared as argument types. E.g.
+ ;; (DEFMETHOD FOO ((X SLOT-OBJECT))
+ ;; (DECLARE (TYPE SLOT-OBJECT X))
+ ;; ..)
+ ;; loses when
+ ;; (DEFSTRUCT BAR A B)
+ ;; (FOO (MAKE-BAR))
+ ;; perhaps because of the way that STRUCTURE-OBJECT
+ ;; inherits both from SLOT-OBJECT and from
+ ;; SB-KERNEL:INSTANCE. In an effort to sweep such
+ ;; problems under the rug, we exclude these problem
+ ;; cases by blacklisting them here. -- WHN 2001-01-19
+ '(slot-object))
+ '(ignorable))
+ ((not (eq *boot-state* 'complete))
+ ;; KLUDGE: PCL, in its wisdom, sometimes calls methods with
+ ;; types which don't match their specializers. (Specifically,
+ ;; it calls ENSURE-CLASS-USING-CLASS (T NULL) with a non-NULL
+ ;; second argument.) Hopefully it only does this kind of
+ ;; weirdness when bootstrapping.. -- WHN 20000610
+ '(ignorable))
+ (t
+ ;; Otherwise, we can make Python very happy.
+ `(type ,specializer ,parameter))))
+
(defun make-method-lambda-internal (method-lambda &optional env)
(unless (and (consp method-lambda) (eq (car method-lambda) 'lambda))
(error "The METHOD-LAMBDA argument to MAKE-METHOD-LAMBDA, ~S, ~
method-lambda))
(multiple-value-bind (documentation declarations real-body)
(extract-declarations (cddr method-lambda) env)
- (let* ((name-decl (get-declaration 'method-name declarations))
- (sll-decl (get-declaration 'method-lambda-list declarations))
+ (let* ((name-decl (get-declaration '%method-name declarations))
+ (sll-decl (get-declaration '%method-lambda-list declarations))
(method-name (when (consp name-decl) (car name-decl)))
(generic-function-name (when method-name (car method-name)))
(specialized-lambda-list (or sll-decl (cadr method-lambda))))
(calls (list nil))
(class-declarations
`(declare
- ;; FIXME: These nonstandard (DECLARE (SB-PCL::CLASS FOO BAR))
- ;; declarations should go away but as of 0.6.9.10, it's not
- ;; as simple as just deleting them.
+ ;; These declarations seem to be used by PCL to pass
+ ;; information to itself; when I tried to delete 'em
+ ;; ca. 0.6.10 it didn't work. I'm not sure how
+ ;; they work, but note the (VARIABLE-DECLARATION '%CLASS ..)
+ ;; expression in CAN-OPTIMIZE-ACCESS1. -- WHN 2000-12-30
,@(remove nil
(mapcar (lambda (a s) (and (symbolp s)
(neq s 't)
- `(class ,a ,s)))
+ `(%class ,a ,s)))
parameters
specializers))
;; These TYPE declarations weren't in the original
- ;; PCL code, but Python likes them a lot. (We're
- ;; telling the compiler about our knowledge of
- ;; specialized argument types so that it can avoid
- ;; run-time type overhead, which can be a big win
- ;; for Python.)
- ,@(mapcar (lambda (a s)
- (cond ((and (consp s)
- (eql (car s) 'eql))
- ;; KLUDGE: ANSI, in its wisdom, says
- ;; that EQL-SPECIALIZER-FORMs in EQL
- ;; specializers are evaluated at
- ;; DEFMETHOD expansion time. Thus,
- ;; although one might think that in
- ;; (DEFMETHOD FOO ((X PACKAGE)
- ;; (Y (EQL 12))
- ;; ..))
- ;; the PACKAGE and (EQL 12) forms are
- ;; both parallel type names, they're
- ;; not, as is made clear when you do
- ;; (DEFMETHOD FOO ((X PACKAGE)
- ;; (Y (EQL 'BAR)))
- ;; ..)
- ;; where Y needs to be a symbol
- ;; named "BAR", not some cons made by
- ;; (CONS 'QUOTE 'BAR). I.e. when
- ;; the EQL-SPECIALIZER-FORM is (EQL 'X),
- ;; it requires an argument to be of
- ;; type (EQL X). It'd be easy to transform
- ;; one to the other, but it'd be somewhat
- ;; messier to do so while ensuring that
- ;; the EQL-SPECIALIZER-FORM is only
- ;; EVAL'd once. (The new code wouldn't
- ;; be messy, but it'd require a big
- ;; transformation of the old code.)
- ;; So instead we punt. -- WHN 20000610
- '(ignorable))
- ((not (eq *boot-state* 'complete))
- ;; KLUDGE: PCL, in its wisdom,
- ;; sometimes calls methods with
- ;; types which don't match their
- ;; specializers. (Specifically, it calls
- ;; ENSURE-CLASS-USING-CLASS (T NULL)
- ;; with a non-NULL second argument.)
- ;; Hopefully it only does this kind
- ;; of weirdness when bootstrapping..
- ;; -- WHN 20000610
- '(ignorable))
- (t
- ;; Otherwise, we can make Python
- ;; very happy.
- `(type ,s ,a))))
+ ;; PCL code, but the Python compiler likes them a
+ ;; lot. (We're telling the compiler about our
+ ;; knowledge of specialized argument types so that
+ ;; it can avoid run-time type dispatch overhead,
+ ;; which can be a huge win for Python.)
+ ;;
+ ;; FIXME: Perhaps these belong in
+ ;; ADD-METHOD-DECLARATIONS instead of here?
+ ,@(mapcar #'parameter-specializer-declaration-in-defmethod
parameters
specializers)))
(method-lambda
(unless was-valid-p
(let ((name (if (eq *boot-state* 'complete)
(generic-function-name gf)
- (early-gf-name gf))))
+ (!early-gf-name gf))))
(esetf (gf-precompute-dfun-and-emf-p arg-info)
(let* ((sym (if (atom name) name (cadr name)))
(pkg-list (cons *pcl-package*
(defvar *sgf-name-index*
(!bootstrap-slot-index 'standard-generic-function 'name))
-(defun early-gf-name (gf)
+(defun !early-gf-name (gf)
(instance-ref (get-slots gf) *sgf-name-index*))
(defun gf-lambda-list (gf)
(defun early-method-standard-accessor-slot-name (early-method)
(seventh (fifth early-method)))
-;;; Fetch the specializers of an early method. This is basically just a
-;;; simple accessor except that when the second argument is t, this converts
-;;; the specializers from symbols into class objects. The class objects
-;;; are cached in the early method, this makes bootstrapping faster because
-;;; the class objects only have to be computed once.
+;;; Fetch the specializers of an early method. This is basically just
+;;; a simple accessor except that when the second argument is t, this
+;;; converts the specializers from symbols into class objects. The
+;;; class objects are cached in the early method, this makes
+;;; bootstrapping faster because the class objects only have to be
+;;; computed once.
+;;;
;;; NOTE:
-;;; the second argument should only be passed as T by early-lookup-method.
-;;; this is to implement the rule that only when there is more than one
-;;; early method on a generic function is the conversion from class names
-;;; to class objects done.
-;;; the corresponds to the fact that we are only allowed to have one method
-;;; on any generic function up until the time classes exist.
+;;; The second argument should only be passed as T by
+;;; early-lookup-method. This is to implement the rule that only when
+;;; there is more than one early method on a generic function is the
+;;; conversion from class names to class objects done. This
+;;; corresponds to the fact that we are only allowed to have one
+;;; method on any generic function up until the time classes exist.
(defun early-method-specializers (early-method &optional objectsp)
(if (and (listp early-method)
(eq (car early-method) :early-method))
(add-method gf new)))
;;; This is the early version of ADD-METHOD. Later this will become a
-;;; generic function. See !FIX-EARLY-GENERIC-FUNCTIONS which has special
-;;; knowledge about ADD-METHOD.
+;;; generic function. See !FIX-EARLY-GENERIC-FUNCTIONS which has
+;;; special knowledge about ADD-METHOD.
(defun add-method (generic-function method)
(when (not (fsc-instance-p generic-function))
(error "Early ADD-METHOD didn't get a funcallable instance."))
(error "Early ADD-METHOD didn't get an early method."))
(push method (early-gf-methods generic-function))
(set-arg-info generic-function :new-method method)
- (unless (assoc (early-gf-name generic-function) *!generic-function-fixups*
+ (unless (assoc (!early-gf-name generic-function)
+ *!generic-function-fixups*
:test #'equal)
(update-dfun generic-function)))
(setf (early-gf-methods generic-function)
(remove method (early-gf-methods generic-function)))
(set-arg-info generic-function)
- (unless (assoc (early-gf-name generic-function) *!generic-function-fixups*
+ (unless (assoc (!early-gf-name generic-function)
+ *!generic-function-fixups*
:test #'equal)
(update-dfun generic-function)))
(set-methods gf methods))))
(sb-int:/show "leaving !FIX-EARLY-GENERIC-FUNCTIONS"))
\f
-;;; PARSE-DEFMETHOD is used by DEFMETHOD to parse the &REST argument into
-;;; the 'real' arguments. This is where the syntax of DEFMETHOD is really
-;;; implemented.
+;;; PARSE-DEFMETHOD is used by DEFMETHOD to parse the &REST argument
+;;; into the 'real' arguments. This is where the syntax of DEFMETHOD
+;;; is really implemented.
(defun parse-defmethod (cdr-of-form)
;;(declare (values name qualifiers specialized-lambda-list body))
(let ((name (pop cdr-of-form))
(unparse-specializers (method-specializers specializers-or-method))))
(defun parse-method-or-spec (spec &optional (errorp t))
- ;;(declare (values generic-function method method-name))
(let (gf method name temp)
(if (method-p spec)
(setq method spec
and not allowing any parameter specializers to follow~%~
to follow it."
arg))
- ;; When we are at a lambda-list keyword, the parameters don't
- ;; include the lambda-list keyword; the lambda-list does include
- ;; the lambda-list keyword; and no specializers are allowed to
- ;; follow the lambda-list keywords (at least for now).
+ ;; When we are at a lambda-list keyword, the parameters
+ ;; don't include the lambda-list keyword; the lambda-list
+ ;; does include the lambda-list keyword; and no
+ ;; specializers are allowed to follow the lambda-list
+ ;; keywords (at least for now).
(multiple-value-bind (parameters lambda-list)
(parse-specialized-lambda-list (cdr arglist) t)
(values parameters
(eval-when (:load-toplevel :execute)
(setq *boot-state* 'early))
\f
-;;; FIXME: In here there was a #-CMU definition of SYMBOL-MACROLET which used
-;;; %WALKER stuff. That suggests to me that maybe the code walker stuff was
-;;; only used for implementing stuff like that; maybe it's not needed any more?
-;;; Hunt down what it was used for and see.
+;;; FIXME: In here there was a #-CMU definition of SYMBOL-MACROLET
+;;; which used %WALKER stuff. That suggests to me that maybe the code
+;;; walker stuff was only used for implementing stuff like that; maybe
+;;; it's not needed any more? Hunt down what it was used for and see.
(defmacro with-slots (slots instance &body body)
(let ((in (gensym)))
(third instance)
instance)))
(and (symbolp instance)
- `((declare (variable-rebinding ,in ,instance)))))
+ `((declare (%variable-rebinding ,in ,instance)))))
,in
(symbol-macrolet ,(mapcar #'(lambda (slot-entry)
(let ((variable-name
(third instance)
instance)))
(and (symbolp instance)
- `((declare (variable-rebinding ,in ,instance)))))
+ `((declare (%variable-rebinding ,in ,instance)))))
,in
(symbol-macrolet ,(mapcar #'(lambda (slot-entry)
(let ((variable-name (car slot-entry))