143 lines
46 KiB
Plaintext
143 lines
46 KiB
Plaintext
Copyright (c) 1986 Xerox Corporation. All rights reserved.
|
||
|
||
15.2.2 Advise Functions
|
||
1
|
||
|
||
ADVISE is a function of four arguments: FN, WHEN, WHERE, and WHAT. FN is the function to be modified by advising, WHAT is the modification, or piece of advice. WHEN is either BEFORE, AFTER, or AROUND, and indicates whether the advice is to operate BEFORE, AFTER, or AROUND the body of the function definition. WHERE specifies exactly where in the list of advice the new advice is to be placed, e.g., FIRST, or (BEFORE PRINT) meaning before the advice containing PRINT, or (AFTER 3) meaning after the third piece of advice, or even (: TTY:). If WHERE is specified, ADVISE first checks to see if it is one of LAST, BOTTOM, END, FIRST, or TOP, and operates accordingly. Otherwise, it constructs an appropriate edit command and calls the editor to insert the advice at the corresponding location.
|
||
Both WHEN and WHERE are optional arguments, in the sense that they can be omitted in the call to ADVISE. In other words, ADVISE can be thought of as a function of two arguments (ADVISE FN WHAT), or a function of three arguments: (ADVISE FN WHEN WHAT), or a function of four arguments: (ADVISE FN WHEN WHERE WHAT). Note that the advice is always the last argument. If WHEN=NIL, BEFORE is used. If WHERE=NIL, LAST is used.
|
||
(ADVISE FN WHEN WHERE WHAT) [Function]
|
||
1
|
||
|
||
FN is the function to be advised, WHEN=BEFORE, AFTER, or AROUND, WHERE specifies where in the advice list the advice is to be inserted, and WHAT is the piece of advice.
|
||
If FN is of the form (FN1 IN FN2), FN1 is changed to FN1-IN-FN2 throughout FN2, as with break, and then FN1-IN-FN2 is used in place of FN. If FN1 and/or FN2 are lists, they are distributed as with BREAK0, ("BREAK0" . Function).
|
||
If FN is broken, it is unbroken before advising.
|
||
If FN is not defined, an error is generated, NOT A FUNCTION.
|
||
If FN is being advised for the first time, i.e., if (GETP FN 'ADVISED)=NIL, a GENSYM is generated and stored on the property list of FN under the property ADVISED, and the GENSYM is defined with the original definition of FN. An appropriate expr definition is then created for FN, using private versions of PROG, SETQ, and RETURN, so that these functions can also be advised. Finally, FN is added to the (front of) ADVISEDFNS, so that (UNADVISE T) always unadvises the last function advised (see ("UNADVISE" . Function)).
|
||
If FN has been advised before, it is moved to the front of ADVISEDFNS.
|
||
If WHEN=BEFORE or AFTER, the advice is inserted in FN's definition either BEFORE or AFTER the original body of the function. Within that context, its position is determined by WHERE. If WHERE=LAST, BOTTOM, END, or NIL, the advice is added following all other advice, if any. If WHERE=FIRST or TOP, the advice is inserted as the first piece of advice. Otherwise, WHERE is treated as a command for the editor, similar to BREAKIN, e.g., (BEFORE 3), (AFTER PRINT).
|
||
If WHEN=AROUND, the body is substituted for * in the advice, and the result becomes the new body, e.g., (ADVISE 'FOO 'AROUND '(RESETFORM (OUTPUT T) *)). Note that if several pieces of AROUND advice are specified, earlier ones will be embedded inside later ones. The value of WHERE is ignored.
|
||
Finally (LIST WHEN WHERE WHAT) is added (by ADDPROP) to the value of property ADVICE on the property list of FN, so that a record of all the changes is available for subsequent use in readvising. Note that this property value is a list of the advice in order of calls to ADVISE, not necessarily in order of appearance of the advice in the definition of FN.
|
||
The value of ADVISE is FN.
|
||
If FN is non-atomic, every function in FN is advised with the same values (but copies) for WHEN, WHERE, and WHAT. In this case, ADVISE returns a list of individual functions.
|
||
1
|
||
|
||
Note: advised functions can be broken. However if a function is broken at the time it is advised, it is first unbroken. Similarly, advised functions can be edited, including their advice. UNADVISE will still restore the function to its unadvised state, but any changes to the body of the definition will survive. Since the advice stored on the property list is the same structure as the advice inserted in the function, editing of advice can be performed on either the function's definition or its property list.
|
||
(UNADVISE X) [NLambda NoSpread Function]
|
||
1
|
||
|
||
An nlambda nospread like UNBREAK. It takes an indefinite number of functions and restores them to their original unadvised state, including removing the properties added by ADVISE. UNADVISE saves on the list ADVINFOLST enough information to allow restoring a function to its advised state using READVISE. ADVINFOLST and READVISE thus correspond to BRKINFOLST and REBREAK. If a function contains the property READVICE, UNADVISE moves the current value of the property ADVICE to READVICE.
|
||
(UNADVISE) unadvises all functions on ADVISEDFNS in reverse order, so that the most recently advised function is unadvised last. It first sets ADVINFOLST to NIL.
|
||
(UNADVISE T) unadvises the first function of ADVISEDFNS, i.e., the most recently advised function.
|
||
1
|
||
|
||
(READVISE X) [NLambda NoSpread Function]
|
||
1
|
||
|
||
An nlambda nospread like REBREAK for restoring a function to its advised state without having to specify all the advise information. For each function on X, READVISE retrieves the advise information either from the property READVICE for that function, or from ADVINFOLST, and performs the corresponding advise operation(s). In addition it stores this information on the property READVICE if not already there. If no information is found for a particular function, value is (FN - NO ADVICE SAVED).
|
||
(READVISE) readvises everything on ADVINFOLST.
|
||
(READVISE T) readvises the first function on ADVINFOLST, i.e., the function most recently unadvised.
|
||
1
|
||
|
||
A difference between ADVISE, UNADVISE, and READVISE versus BREAK, UNBREAK, and REBREAK, is that if a function is not rebroken between successive (UNBREAK)'s, its break information is forgotten. However, once READVISE is called on a function, that function's advice is permanently saved on its property list (under READVICE); subsequent calls to UNADVISE will not remove it. In fact, calls to UNADVISE update the property READVICE with the current value of the property ADVICE, so that the sequence READVISE, ADVISE, UNADVISE causes the augmented advice to become permanent. Note that the sequence READVISE, ADVISE, READVISE removes the "intermediate advice" by restoring the function to its earlier state.
|
||
(ADVISEDUMP X FLG) [Function]
|
||
1
|
||
|
||
Used by PRETTYDEF when given a command of the form (ADVISE ...) or (ADVICE ...). If FLG=T, ADVISEDUMP writes both a DEFLIST and a READVISE (this corresponds to (ADVISE ...)). If FLG=NIL, only the DEFLIST is written (this corresponds to (ADVICE ...)). In either case, ADVISEDUMP copies the advise information to the property READVICE, thereby making it "permanent" as described above.
|
||
1
|
||
|
||
|