From: Christophe R. <cs...@ca...> - 2003-01-23 18:15:50
|
Hi, I'm posting here because I've lost track of which PCL trees are where, and also how to build with all of them, and because I believe I have uncovered two subtle bugs that may or may not have easy test cases or resolutions -- I hope maintainers of other PCL trees will chip in because, frankly, I'm baffled. The first, as reported by Stig Sand=F8 on #lisp IRC, is an annoyance rather than a critical bug. But it's quite an annoyance, as can be seen from the following transcript: * (defclass foo () ()) =20=20 #<STANDARD-CLASS FOO> * (defmethod bar ((x foo) (foo foo)) (call-next-method) x) ; in: LAMBDA NIL ; (SB-PCL::FAST-LEXICAL-METHOD-FUNCTIONS ; ((X FOO) SB-PCL::.NEXT-METHOD-CALL. (X FOO) NIL :CALL-NEXT-METHOD-P T ; :NEXT-METHOD-P-P NIL :METHOD-NAME-DECLARATION ((BAR #)) ...) ; (BLOCK BAR (CALL-NEXT-METHOD) X)) ; --> SB-PCL::BIND-FAST-LEXICAL-METHOD-MACROS MACROLET=20 ; --> SB-PCL::BIND-LEXICAL-METHOD-FUNCTIONS SB-PCL::CALL-NEXT-METHOD-BIND= LET=20 ; --> FLET BLOCK SB-PCL::CALL-NEXT-METHOD-BODY IF IF SB-PCL::BIND-ARGS LE= T*=20 ; --> SB-PCL::INVOKE-EFFECTIVE-METHOD-FUNCTION PROGN COND IF PROGN=20 ; --> SB-PCL::INVOKE-FAST-METHOD-CALL SB-PCL::FMC-FUNCALL FUNCALL=20 ; =3D=3D> ; FOO ;=20 ; note: deleting unreachable code =20=20 ; --> SB-PCL::BIND-FAST-LEXICAL-METHOD-MACROS MACROLET=20 ; --> SB-PCL::BIND-LEXICAL-METHOD-FUNCTIONS SB-PCL::CALL-NEXT-METHOD-BIND= LET=20 ; --> FLET BLOCK SB-PCL::CALL-NEXT-METHOD-BODY IF IF SB-PCL::BIND-ARGS LE= T*=20 ; --> SB-PCL::INVOKE-EFFECTIVE-METHOD-FUNCTION PROGN COND IF COND IF COND= IF=20 ; --> PROGN ETYPECASE LET COND IF PROGN SB-PCL::INVOKE-METHOD-CALL=20 ; --> SB-PCL::INVOKE-METHOD-CALL1 LET LIST=20 ; =3D=3D> ; FOO ;=20 ; note: deleting unreachable code =20=20 ; --> SB-PCL::BIND-FAST-LEXICAL-METHOD-MACROS MACROLET=20 ; --> SB-PCL::BIND-LEXICAL-METHOD-FUNCTIONS SB-PCL::CALL-NEXT-METHOD-BIND= LET=20 ; --> FLET BLOCK SB-PCL::CALL-NEXT-METHOD-BODY IF IF SB-PCL::BIND-ARGS LE= T*=20 ; --> SB-PCL::INVOKE-EFFECTIVE-METHOD-FUNCTION PROGN COND IF COND IF COND= IF=20 ; --> PROGN ETYPECASE LET COND IF COND IF PROGN FUNCALL=20 ; =3D=3D> ; FOO ;=20 ; note: deleting unreachable code ; compilation unit finished ; printed 3 notes STYLE-WARNING: implicitly creating new generic function BAR #<STANDARD-METHOD BAR (FOO FOO) {916D179}> These code deletion notes only occur when a variable has the same name as a class in the defmethod lambda list, and also when there is more than one argument, in current SBCL. My current suspicion falls on SPLIT-DECLARATIONS, which splits the SB-PCL::%CLASS (PCL::CLASS in CMUCL) declarations differently if a variable name and a class name in the defmethod lambda list are the same, but I am still somewhat at a loss to explain all this excitement from the compiler. I note in passing that the %CLASS declaration takes its arguments in the other order from TYPE declarations... The second is even harder to pin down, though a priori it looks obviously wrong; I haven't even been able to construct a test case for it, even though one such should be easy. Consider the following fragment from INVOKE-EFFECTIVE-METHOD-FUNCTION (which is much the same in CMUCL's PCL): ,@(when (and (null restp) (=3D 2 (length required-args+rest-arg))) `(((typep ,emf 'fixnum) (let ((.new-value. ,(car required-args+rest-arg)) (.slots. (get-slots-or-nil ,(car required-args+rest-arg)))) (when .slots. (setf (clos-slots-ref .slots. ,emf) .new-value.)))))) We have previously deduced that a FIXNUM representation of an EMF represents a slot access -- and if the function has two arguments, this would be a slot set. So we do something that gets the slots, and sets the required slot (encoded in the EMF) to the new value. Um. Except that there's clearly a typo here, because we are obtaining both the .NEW-VALUE. and the .SLOTS. variables from the first element of REQUIRED-ARGS+REST-ARG. So, is this dead code? I can't trigger the bug -- maybe someone else can? The third bug is one that in all probability affects sbcl only; again, it's only an annoyance. Its demonstration is quite simple: * (defmethod foo ((x integer)) (class-of x)) ; in: LAMBDA NIL ; (CLASS-OF X) ; --> BLOCK SB-KERNEL:LAYOUT-CLASS SB-KERNEL:LAYOUT-OF BLOCK COND IF COND= IF=20 ; --> COND IF PROGN LOCALLY=20 ; =3D=3D> ; (SB-KERNEL:CLASS-LAYOUT (FIND-CLASS 'NULL)) ;=20 ; note: deleting unused function ; SB-KERNEL:CLASS-LAYOUT ; compilation unit finished ; printed 1 note This presumably comes from the inlining of SB-KERNEL:LAYOUT-OF, but why does only this branch trigger the code deletion note? And how can we shut it up sanely? (The comments in SB-KERNEL:LAYOUT-OF make me tremble with fear...) Any advice is welcome... my head hurts. Cheers, Christophe --=20 http://www-jcsu.jesus.cam.ac.uk/~csr21/ +44 1223 510 299/+44 7729 383= 757 (set-pprint-dispatch 'number (lambda (s o) (declare (special b)) (format s = b))) (defvar b "~&Just another Lisp hacker~%") (pprint #36rJesusCollegeCambri= dge) |