[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [spr8063] Tracing SETF on structures



[This matter has been assigned the tracking identifier "spr8063".
Please refer to it in any followup communication.  Also, be sure
to cc bugs@franz.com so that if I am unavailable someone else will
be able to respond.]

   From: jmccarth%stimpy@cs.umass.edu (Joe McCarthy)

   We have a structure defined by

   (DEFSTRUCT NP-RECORD
     ...
     RELATED-NP
     ...)

   and we would like to be able to set up tracing so that we can see
   whenever the RELATED-NP field of an NP-RECORD is changed, i.e.,,
   whenever a form such as

	   (SETF (NP-RECORD-RELATED-NP <np-record>)
		 <new-value>)

   is executed.  In Section 5.4 of the Allegro CL Common Lisp User Guide
   (Version 4.1, March 1992, page 5-29), the following example is given:

	   (trace ((method (setf slot-1) (t baz))))
	   (trace ((method foo :before (integer))))
	   (trace ((method foo :after (integer))))

   Unfortunately, I am unable to interpret how I can use this example to
   set up the tracing I want.  In particular, I'm not sure what SLOT-1,
   and (T BAZ) mean.

   Taking a guess at a mapping, I tried the following

	   (trace ((method (setf related-np) (t np-record))))

   but this yielded:

   Error: (METHOD (SETF RELATED-NP) (T NP-RECORD)) does not have a function
	  definition

   Can anyone help me figure out how to set up the desired tracing?

The short answer is that you can't.  The only thing that can be traced
is a function.  The language does not specify _how_ defstruct slots
are interfaced to the SETF macro.  Although defining CLOS-like setf
functions with names like (SETF SLOT-1) would be one plausible
implementation, another much more traditional implementation is to
define them as if by DEFSETF.  This means that setf expansions of
defstruct slot accessor functions in most implementations macroexpand
into some sort of imlementation-dependent code.  This is not much
different from the traditional inlining of the slot accessors
themselves on most implementations, except that since the accessor is
a real function with a real name, you can prevent the inlining by
declaring or proclaiming it NOTINLINE.  But defstruct settors aren't
functions and don't have names, so you can't make declaratons on nor
trace them.

The only thing you can do would be to define the slot accessors under
different names.  Macrology would make this more palatable, but the
basic idea would be:

   (defstruct (foo (:conc-name :.foo-)) slot-1)

   (defun foo-slot-1 (x) (.foo-slot-1 x))

   (defun (setf foo-slot-1) (v x) (setf (.foo-slot-1 x) v))

Since the `public' names FOO-SLOT-1 and (SETF FOO-SLOT-1) are now real
functions (with the corresponding runtime overhead) they can reliably
be traced.  The syntax for the setf function is (TRACE ((SETF
FOO-SLOT-1))).