Add means to recover method definitions from method objects

Bug #1819015 reported by Paul F. Dietz
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
SBCL
New
Undecided
Unassigned

Bug Description

One can get the definition of ordinary functios using FUNCTION-LAMBDA-EXPRESSION (if the function was in a LOADed file, rather than from a fasl, or was defined by eval-ing a defun, or calling COMPILE on a lambda expression), but there is nothing similar for methods.

Add a means for obtaining the source for a method from the method object, and also a means of replacing and restoring a method object for a generic function.

It might be necessary to cheat a bit due to methods being defined in a lexical environment which may no longer be available, but that applies to the lambda expression from FUNCTION-LAMBDA-EXPRESSION as well.

The use case for this is to do mutation testing on Common Lisp code. This would involve getting the definitions of functions and methods, mutating them, and seeing if the test suite kills the mutants.

description: updated
description: updated
Revision history for this message
Douglas Katzman (dougk) wrote :

You can somewhat already do this, but function-lambda-expression give you a form that isn't as simple as you'd like. e.g. after doing (declaim (optimize sb-c:store-source-form))
then you can recover method expressions thusly:

* (function-lambda-expression
   (sb-pcl::%method-function-fast-function
    (sb-mop:method-function (find-method #'foozelize nil (list 'string)))))

(LAMBDA (SB-PCL::.PV. SB-PCL::.NEXT-METHOD-CALL. SELF)
  (DECLARE (IGNORABLE SB-PCL::.PV. SB-PCL::.NEXT-METHOD-CALL.)
           (DISABLE-PACKAGE-LOCKS SB-PCL::PV-ENV-ENVIRONMENT))
  (DECLARE (SB-PCL::%PARAMETER SELF))
  (DECLARE (TYPE STRING SELF))
  (DECLARE (IGNORABLE SELF))
  (SYMBOL-MACROLET ((SB-PCL::PV-ENV-ENVIRONMENT SB-PCL::DEFAULT))
    (SB-PCL::FAST-LEXICAL-METHOD-FUNCTIONS ((SELF) SB-PCL::.NEXT-METHOD-CALL.
                                            (SELF) NIL :CALL-NEXT-METHOD-P NIL
                                            :SETQ-P NIL :PARAMETERS-SETQD NIL
                                            :METHOD-CELL (#:METHOD-CELL)
                                            :APPLYP NIL)
      (DECLARE (SB-PCL::%CLASS SELF STRING))
      (LOCALLY
       (DECLARE (DISABLE-PACKAGE-LOCKS SB-PCL::%PARAMETER-BINDING-MODIFIED))
       (SYMBOL-MACROLET ((SB-PCL::%PARAMETER-BINDING-MODIFIED (QUOTE)))
         (DECLARE (ENABLE-PACKAGE-LOCKS SB-PCL::%PARAMETER-BINDING-MODIFIED))
         (BLOCK FOOZELIZE `(FOOZELIZED ,SELF)))))))

which is a complicated lambda coming from the rather simple source form:
(defmethod foozelize ((self string)) `(foozelized ,self))

This is, strictly speaking, analogous to DEFUN in that additional constructs are wrapped around the forms which literally appeared in source. e.g. (defun zot (y) (list (foo y))) leads to
(function-lambda-expression #'zot) => (LAMBDA (Y) (BLOCK ZOT (LIST (FOO Y))))

So in theory the information is available and I'm not sure the system per se ought to offer a way to extract the original lambda verbatim.
A major reason for not doing exactly what this request asks is that you'd have to think about the implications of passing that information all the way down to the guts of CLOS and not breaking anything about metaobject protocol. Specifically I'd be wary of the defmethod macro passing a quoted version of its original body to the programmatic method creator functions.
In addition to the resulting code bloat (if enabled by default), you then have the usual problems of forms that themselves are not re-externalizable for whatever reason. (It happens, and of course the STORE-SOURCE-FORM declaration is subject to that same problem, but it handles it by silently not recording the source, which is possible only by relying on compiler internals)

If you can figure out how to reverse-engineer the above form into something prettier, such logic would be suitable as an addition to sb-introspect I think.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.