Most GFP operators are defined using a macro called defgfpop . This macro creates several definitions for an operator named op, depending on the settings of the various features. It always produces a function and a compiler macro that are both called op, both of which are defined to call a method called op-internal. When :gfp-frame-coersion is enabled, the function and compiler macro also include code to coerce their frame arguments (if any) to frame objects (the exact coersion code is influenced by arguments to defgfpop .) After the call to op-internal, we insert code supplied in the monitor-body argument to defgfpop , if any (when :monitor-gfp is enabled).
A default method is created for op-internal that includes code specified under the default-body argument to defgfpop . If code is supplied in the modification-body argument to defgfpop , that code is inserted in an after-method for op-internal (when :gfp-record-modifications is enabled).
The reason for not putting the monitor code in a method for op-internal is that we only want to record user-level references to GFP functions, not internal references. On the other hand, we want all references to be recorded by the modification body, so it must be put in a method. This point requires elaboration because it implies an important constraint on how FRS-specific methods for GFP operations should be written. Imagine that get-slot-value is implemented by taking the car of the result returned by get-slot-values . If not implemented correctly, the monitoring code might record two references to a given frame whenever the user code called get-slot-values on that frame (one recorded by the monitor body of get-slot-values and one by the call of get-slot-value within get-slot-values . But, only one reference should be recorded because the user code has made only one call. The solution is that the implementation of all GFP methods should only call the -internal forms of other GFP methods. So in our example, the implementation of get-slot-value must call get-slot-values-internal not get-slot-values . This approach has the disadvantage that because the -internal forms of the methods do not support keyword arguments, all arguments must be supplied in the -internal call. But otherwise, this appears to be the best approach possible.
One final implication of this implementation strategy is that since arguments are coerced to frame objects at the op level rather than the op-internal level, the op-internal methods can assume that their frame arguments have already been coerced to frame objects -- they need do no coersion. A few obvious operations are exceptions, such as coerce-to-frame (i.e., by definition of the operation, the argument coerce-to-frame-internal cannot be guaranteed to be coerced to a frame object by coerce-to-frame coerce-to-frame-internal is to do any work).