[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
7/7 bugs
- To: CommonLoops.pa@Xerox.COM
- Subject: 7/7 bugs
- From: kanderso@WILMA.BBN.COM
- Date: Wed, 27 Jul 88 16:50:00 -0400
- Cc: kanderson@WILMA.BBN.COM
- Redistributed: CommonLoops.pa
Here are some questions, bug reports, and bug fixes for 7/7/88 PCL:
1. Question: Why is DEFINE-BUILT-IN-CLASSES no longer a macro? I
presume it is to avoid the explicit COMPILE the old version had. What
is the right way for users to add their own built ins?
2. Question: In METHODS.LISP and probably elsewhere there are methods
specialized on T when they should be specialized on GENERIC-FUNCTION,
say. Is there a good reason for this? Specializing them on T
invalidates them unnecesarily every time a new class is defined.
3. Bug: On 3600's M-. only finds method definitions that have been
seen by ZMACS, not just loaded it.
4. Gregor's latest version of expand-with-slots had an argument
reversed. This version seems to work:
(defun expand-with-slots (specs whole body env gensym instance translate-fn)
(DECLARE (IGNORE WHOLE)) ; KRA
(walk-form
`(let ((,gensym ,instance))
,@(and (symbolp instance)
`((declare (variable-rebinding ,gensym ,instance))))
,GENSYM ; KRA: avoid compiler warnings
,@body)
env
#'(lambda (f c e)
(declare (ignore e))
(expand-with-slots-internal specs
f
c
translate-fn))))
5. EXPAND-DEFMETHOD-INTERNAL didn't seem to work right when a method
contained a CALL-NEXT-METHOD because variables like .ISL. and .PV.
were declared special. This version also fixes Jim Larus' complaint
about IGNORE declarations.
(defun expand-defmethod-internal
(generic-function-name qualifiers specialized-lambda-list body env)
(declare (values fn-form specializers doc)
(ignore qualifiers))
(multiple-value-bind (documentation declarations real-body)
(extract-declarations body)
(multiple-value-bind (parameters lambda-list specializers)
(parse-specialized-lambda-list specialized-lambda-list)
(let* ((required-parameters
(mapcar #'(lambda (r s) (declare (ignore s)) r)
parameters
specializers))
(parameters-to-reference
(remove nil
(FLET ((IGNORED-P (S) ; Is S declared ignored?
(DOLIST (D (CDR (FIRST DECLARATIONS)))
(WHEN (AND (EQ (FIRST D) 'IGNORE)
(MEMBER S (CDR D)))
(RETURN T)))))
(mapcar #'(lambda (s r)
(declare (ignore r))
(and (listp s) (NOT (IGNORED-P (CAR S)))
(car s)))
specialized-lambda-list
required-parameters))))
(class-declarations
`(declare
,@(remove nil
(mapcar #'(lambda (a s) (and (symbolp s)
(neq s 't)
`(class ,a ,s)))
parameters
specializers))))
(method-lambda
;; Remove the documentation string and insert the
;; appropriate class declarations. The documentation
;; string is removed to make it easy for us to insert
;; new declarations later, they will just go after the
;; cadr of the method lambda. The class declarations
;; are inserted to communicate the class of the method's
;; arguments to the code walk.
(let ()
`(lambda ,lambda-list
,class-declarations
,@declarations
,@PARAMETERS-TO-REFERENCE
(block ,generic-function-name ,@real-body))))
(call-next-method-p nil) ;flag indicating that call-next-method
;should be in the method definition
(next-method-p-p nil) ;flag indicating that next-method-p
;should be in the method definition
(save-original-args nil) ;flag indicating whether or not the
;original arguments to the method
;must be preserved. This happens
;for two reasons:
; - the method takes &mumble args,
; so one of the lexical functions
; might be used in a default value
; form
; - call-next-method is used without
; arguments at least once in the
; body of the method
(original-args ())
(applyp nil) ;flag indicating whether or not the
;method takes &mumble arguments. If
;it does, it means call-next-method
;without arguments must be APPLY'd
;to original-args. If this gets set
;true, save-original-args is set so
;as well
(slots (mapcar #'list required-parameters))
(plist ())
(walked-lambda nil))
(flet ((walk-function (form context env)
(cond ((not (eq context ':eval)) form)
((not (listp form)) form)
((eq (car form) 'call-next-method)
(setq call-next-method-p 't)
(setq save-original-args (not (cdr form)))
form)
((eq (car form) 'next-method-p)
(setq next-method-p-p 't)
form)
((and (eq (car form) 'function)
(cond ((eq (cadr form) 'call-next-method)
(setq call-next-method-p 't)
(setq save-original-args 't)
form)
((eq (cadr form) 'next-method-p)
(setq next-method-p-p 't)
form)
(t nil))))
((and (or (eq (car form) 'slot-value)
(eq (car form) 'set-slot-value))
(symbolp (cadr form))
(constantp (caddr form)))
(multiple-value-bind (parameter class)
(can-optimize-access (cadr form) env)
(declare (ignore parameter))
(if class
(ecase (car form)
(slot-value
(optimize-slot-value class form))
(set-slot-value
(optimize-set-slot-value class form)))
form)))
((eq (car form) 'standard-instance-access)
(multiple-value-bind (parameter class)
(can-optimize-access (cadr form) env)
(if class
(optimize-standard-instance-access class
parameter
form
slots)
form)))
(t form))))
(maybe-warn-about-redundant-ignores declarations
parameters-to-reference
generic-function-name
specializers)
(setq walked-lambda (walk-form method-lambda env #'walk-function))
;; Scan the lambda list to determine whether this method
;; takes &mumble arguments. If it does, we set applyp
;; and save-original-args true.
;;
;; This is also the place where we construct the original arguments
;; lambda list if there has to be one.
(dolist (p lambda-list)
(if (memq p lambda-list-keywords)
(if (eq p '&aux)
(let ((aux (memq '&aux lambda-list)))
(dolist (a aux) (push a original-args))
(return nil))
(progn
(setq applyp t
save-original-args t)
(push '&rest original-args)
(push (make-symbol "AMPERSAND-ARGS") original-args)
(return nil)))
(push (make-symbol (symbol-name p)) original-args)))
(setq original-args (if save-original-args
(nreverse original-args)
()))
(multiple-value-bind (ignore walked-declarations walked-lambda-body)
(extract-declarations (cddr walked-lambda))
(declare (ignore ignore))
(when (some #'cdr slots)
(setq slots (sort-slots-into-isl slots))
(setq plist (list* :isl slots plist))
(setq walked-lambda-body (add-pv-binding walked-lambda-body
plist
required-parameters
specializers))
(SETQ WALKED-LAMBDA `(LAMBDA ,LAMBDA-LIST ; KRA where should this go?
,@WALKED-DECLARATIONS
,.WALKED-LAMBDA-BODY)))
(when (or next-method-p-p call-next-method-p)
(setq plist (list* :needs-next-methods-p 't plist)))
(values
`(function ,(if (or call-next-method-p next-method-p-p)
(add-lexical-functions-to-method-lambda
walked-declarations
walked-lambda-body
walked-lambda
original-args
lambda-list
save-original-args
applyp
call-next-method-p
next-method-p-p)
`(lambda ,lambda-list
,@walked-declarations
,.walked-lambda-body)))
specializers
documentation
plist)))))))