;;; -*- Mode:gate; Fonts:(HL12 HL12I HL12B CPTFONTB HL12BI HL12B HL12I ) -*- =Node: Function-Defining Special Forms =Text: 3FUNCTION-DEFINING SPECIAL FORMS* 2defun* is a special form that is put in a program to define a function; 2defsubst* and 2macro* are others. This section explains how these special forms work, how they relate to the different kinds of functions, and how they interface to the rest of the function-manipulation system. Function-defining special forms typically take as arguments a function spec and a description of the function to be made, usually in the form of a list of argument names and some forms that constitute the body of the function. They construct a function, give it the function spec as its name, and define the function spec to be the new function. Different special forms make different kinds of functions. 2defun* makes a 2named-lambda* function, and 2defsubst* makes a 2named-subst* function. 2macro* makes a macro; though the macro definition is not really a function, it is like a function as far as definition handling is concerned. These special forms are used in writing programs because the function names and bodies are constants. Programs that define functions usually want to compute the functions and their names, so they use 2fdefine*. See 4(FUNCTIONS-2)How Programs Manipulate Function Specs*. All of these function-defining special forms alter only the basic definition of the function spec. Encapsulations are preserved. See 4(FUNCTIONS-2)Encapsulations*. The special forms only create interpreted functions. There is no special way of defining a compiled function. Compiled functions are made by compiling interpreted ones. The same special form that defines the interpreted function, when processed by the compiler, yields the compiled function. See 4(COMPILER-0)The Compiler* for details. Note that the editor understands these and other ``defining'' special forms (e.g. 2defmethod*, 2defvar*, 2defmacro*, 2defstruct*, etc.) to some extent, so that when you ask for the definition of something, the editor can find it in its source file and show it to you. The general convention is that anything that is used at top level (not inside a function) and starts with 2def* should be a special form for defining things and should be understood by the editor. 2defprop* is an exception. The 2defun* special form (and the 2defunp* macro which expands into a 2defun*) are used for creating ordinary interpreted functions (see 4(FUNCTIONS-1)Simple Function Definitions*). For Maclisp compatibility, a 1type* symbol may be inserted between 1name* and 1lambda-list* in the 2defun* form. The following types are understood: 2expr* The same as no type. 2fexpr* 2"e* and 2&rest* are prefixed to the lambda list. 2macro* A macro is defined instead of a normal function. If 1lambda-list* is a non-2nil* symbol instead of a list, the function is recognized as a Maclisp 1lexpr* and it is converted in such a way that the 2arg*, 2setarg*, and 2listify* functions can be used to access its arguments (see 4(FUNCTIONS-2)Maclisp Lexprs*). The 2defsubst* special form is used to create substitutible functions. It is used just like 2defun* but produces a list starting with 2named-subst* instead of one starting with 2named-lambda*. The 2named-subst* function acts just like the corresponding 2named-lambda* function when applied, but it can also be open-coded (incorporated into its callers) by the compiler. See 4(MACROS-1)Substitutable Functions* for full information. The 2macro* special form is the primitive means of creating a macro. It gives a function spec a definition that is a macro definition rather than a actual function. A macro is not a function because it cannot be applied, but it 1can* appear as the car of a form to be evaluated. Most macros are created with the more powerful 2defmacro* special form. See 4(MACROS-0)Macros*. The 2defselect* special form defines a select-method function. See 4(FUNCTIONS-2)Function-Defining Special Forms*. Unlike the above special forms, the next two (2deff* and 2def*) do not create new functions. They simply serve as hints to the editor that a function is being stored into a function spec here, and therefore if someone asks for the source code of the definition of that function spec, this is the place to look for it. 3def* 1Special Form* If a function is created in some strange way, wrapping a 2def* special form around the code that creates it informs the editor of the connection. The form 3(def 1function-spec** 3 1form1* 1form2*...)* simply evaluates the forms 1form1*, 1form2*, etc. It is assumed that these forms will create or obtain a function somehow, and make it the definition of 1function-spec*. Alternatively, you could put 2(def 1function-spec*)* in front of or anywhere near the forms which define the function. The editor only uses it to tell which line to put the cursor on. 3deff* 1function-spec* 1definition-creator* 1Special Form* 2deff* is a simplified version of 2def*. It evaluates the form 1definition-creator*, which should produce a function, and makes that function the definition of 1function-spec*, which is not evaluated. 2deff* is used for giving a function spec a definition which is not obtainable with the specific defining forms such as 2defun*. For example, 3(deff foo 'bar)* makes 2foo* equivalent to 2bar*, with an indirection so that if 2bar* changes 2foo* will likewise change; conversely, 3(deff foo (function bar))* copies the definition of 2bar* into 2foo* with no indirection, so that further changes to 2bar* will have no effect on 2foo*. 3deff-macro* 1function-spec* 1definition-creator* 1Special Form* Is like 2deff* (see 4(FUNCTIONS-2)Function-Defining Special Forms*) but for defining macros. 1definition-creator* is evaluated to produce a suitable definition-as-a-macro and then 1function-spec* is defined that way. The definition-as-a-macro should be a cons whose car is 2macro* and whose cdr is an expander function. Alternatively, a definition as a subst function can be used; either a list starting with 2subst* or 2named-subst* or a FEF which records it was compiled from such a list. The difference between 2deff* and 2deff-macro* is that 2compile-file* assumes that 2deff-macro* is defining something which should be expanded during compilation. For the rest of the file, the macro defined here is available for expansion. When the file is ultimately loaded, or if compilation is done in-core, 2deff* and 2deff-macro* are equivalent. 1@@define* 1Macro* This macro turns into 2nil*, doing nothing. It exists for the sake of the @ listing generation program, which uses it to declare names of special forms that define objects (such as functions) that @ should cross-reference. 3si:defun-compatibility* 1x* This function is used by 2defun* and the compiler to convert Maclisp-style lexpr, fexpr, and macro 2defun*s to Zetalisp definitions. 1x* should be the cdr of a 2(defun ...)* form. 2defun-compatibility* returns a corresponding 2(defun ...)* or 2(macro ...)* form, in the usual Zetalisp format. You shouldn't ever need to call this yourself. 3defselect* 1Special Form* 2defselect* defines a function which is a select-method. This function contains a table of subfunctions; when it is called, the first argument, a symbol on the keyword package called the 1operation*, is looked up in the table to determine which subfunction to call. Each subfunction can take a different number of arguments and have a different pattern of arguments. 2defselect* is useful for a variety of ``dispatching'' jobs. By analogy with the more general message-passing facilities described in 4(FLAVOR-0)Objects, Message Passing, and Flavors*, the subfunctions are called 1methods* and the list of arguments is sometimes called a 1message*. The special form looks like 3(defselect (1function-spec* 1default-handler* 1no-which-operations*)* 3 (1operation* (1args...*)* 3 1body...*)* 3 (1operation* (1args...*)* 3 1body...*)* 3 ...)* 1function-spec* is the name of the function to be defined. 1default-handler* is optional; it must be a symbol and is a function which gets called if the select-method is called with an unknown operation. If 1default-handler* is unsupplied or 2nil*, then an unknown operation causes an error with condition name 2sys:unclaimed-message* (see 4(FLAVOR-2)Flavor Functions*). Normally, methods for the operations 2:which-operations*, 2:operation-handled-p* and 2:send-if-handles* are generated automatically based on the set of existing methods. These operations have the same meaning as they do on flavor instances; see 4(FLAVOR-4)Vanilla Flavor* for their definitions. If 1no-which-operations* is non-2nil*, these methods are not created automatically; however, you can supply them yourself. If 1function-spec* is a symbol, and 1default-handler* and 1no-which-operations* are not supplied, then the first subform of the 2defselect* may be just 1function-spec* by itself, not enclosed in a list. The remaining subforms in a 2defselect* are the clauses, each defining one method. 1operation* is the operation to be handled by this clause or a list of several operations to be handled by the same clause. 1args* is a lambda-list; it should not include the first argument, which is the operation. 1body* is the body of the function. A clause can instead look like: 3 (1operation* . 1symbol*)* In this case, 1symbol* is the name of a function that is to be called when the 1operation* operation is performed. It will be called with the same arguments as the select-method, including the operation symbol itself. The individual methods of the 2defselect* can be examined, redefined, traced, etc. using 2:select-method* function specs (see 4(FUNCTIONS-1)Function Specs*). 3defselect-incremental* 1function-spec* 1default-handler* 1Special Form* 2defselect* defines a select-method function all at once. By contrast, 2defselect-incremental* defines an empty select-method to which methods can be added with 2defun*. Specifically, 2defselect-incremental* 1function-spec*, with just a default handler and the standard methods 2:which-operations*, 2:operation-handled-p* and 2:send-if-handles*. Individual methods are defined by using 2defun* on a function spec of the form 2(:select-method* 1function-spec2 *operation2)**. 1function-spec* specifies where to find the select-method, and 1operation* is the operation for which a method should be defined. The argument list of the 2defun* must include a first argument which receives the operation name. Example: 3(defselect-incremental foo ignore)* 3 ;2The function ignore is the default handler** 3(defun (:select-method foo :lose) (ignore a)* 3 (1+ a))* defines the same function 3foo* as 3(defselect (foo ignore)* 3 (:lose (a) (1+ a)))* These two examples are not completely equivalent, however. Reevaluating the 2defselect* gets rid of any methods that used to exist but have been deleted from the 2defselect* itself. Reevaluating the 2defselect-incremental* has no such effect, and reevaluating an individual 2defun* redefines only that method. Methods can be removed only with 2fundefine*. =Node: Maclisp Lexprs =Text: 3MACLISP LEXPRS* Lexprs are the way Maclisp functions can accept variable numbers of arguments. They are supported for compatibility only; 2&optional* and 2&rest* are much preferable. A lexpr definition looks like 3(defun foo nargs 1body*...)* where a symbol (2nargs*, here) appears in place of a lambda-list. When the function is called, 2nargs* is bound to the number of arguments it was given. The arguments themselves are accessed using the functions 2arg*, 2setarg*, and 2listify*. 3arg* 1x* 2(arg nil)*, when evaluated during the application of a lexpr, gives the number of arguments supplied to that lexpr. This is primarily a debugging aid, since lexprs also receive their number of arguments as the value of their 2lambda*-variable. 2(arg 1i*)*, when evaluated during the application of a lexpr, gives the value of the 1i*'th argument to the lexpr. 1i* must be a fixnum in this case. It is an error if 1i* is less than 1 or greater than the number of arguments supplied to the lexpr. Example: 3(defun foo nargs ;2define a lexpr *foo.* 3 (print (arg 2)) ;2print the second argument.** 3 (+ (arg 1) ;2return the sum of the first** 3 (arg (- nargs 1)))) ;2and next to last arguments.* setarg* 1i* 1x* 2setarg* is used only during the application of a lexpr. 2(setarg 1i x*)* sets the lexpr's 1i*'th argument to 1x*. 1i* must be greater than zero and not greater than the number of arguments passed to the lexpr. After 2(setarg 1i x*)* has been done, 2(arg 1i*)* returns 1x*. 3listify* 1n* 2(listify 1n*)* manufactures a list of 1n* of the arguments of a lexpr. With a positive argument 1n*, it returns a list of the first 1n* arguments of the lexpr. With a negative argument 1n*, it returns a list of the last 2(abs 1n*)* arguments of the lexpr. Basically, it works as if defined as follows: 3(defun listify (n)* 3 (cond ((minusp n)* 3 (listify1 (arg nil) (+ (arg nil) n 1)))* 3 (t* 3 (listify1 n 1))))* 3(defun listify1 (n m) ;2 auxiliary function.** 3 (do ((i n (1- i))* 3 (result nil (cons (arg i) result)))* 3 ((< i m) result)))* =Node: How Programs Manipulate Function Specs =Text: 3HOW PROGRAMS MANIPULATE FUNCTION SPECS fdefine* 1function-spec* 1definition* &optional 1(carefully* 3nil1)** 1(no-query* 3nil1)** This is the primitive used by 2defun* and everything else in the system to change the definition of a function spec. If 1carefully* is non-2nil*, which it usually should be, then only the basic definition is changed; the previous basic definition is saved if possible (see 2undefun*, 4(FUNCTIONS-2)How Programs Manipulate Function Specs*), and any encapsulations of the function such as tracing and advice are carried over from the old definition to the new one. 1carefully* also causes the user to be queried if the function spec is being redefined by a file different from the one that defined it originally. However, this warning is suppressed if either the argument 1no-query* is non-2nil*, or if the global variable 2inhibit-fdefine-warnings* is 2t*. If 2fdefine* is called while a file is being loaded, it records what file the function definition came from so that the editor can find the source code. If 1function-spec* was already defined as a function, and 1carefully* is non-2nil*, the function-spec's 2:previous-definition* property is used to save the previous definition. This property is used by the 2undefun* function (4(FUNCTIONS-2)How Programs Manipulate Function Specs*), which restores the previous definition. The properties for different kinds of function specs are stored in different places; when a function spec is a symbol its properties are stored on the symbol's property list. 2defun* and the other function-defining special forms all supply 2t* for 1carefully* and 2nil* or nothing for 1no-query*. Operations that construct encapsulations, such as 2trace*, are the only ones which use 2nil* for 1carefully*. 3si:record-source-file-name* 1name* &optional 1(type* 3defun1)** 1no-query* Records a definition of 1name*, of type 1type*. 1type* should be 2defun* to record a function definition; then 1name* is a function spec. 1type* can also be 2defvar*, 2defflavor*, 2defresource*, 2defsignal* or anything else you want to use. The value of 2sys:fdefine-file-pathname* is assumed to be the generic pathname of the file the definition is coming from, or 2nil* if the definition is not from a file. If a definition of the same 1name* and 1type* has already been seen but not in the same file, and 1no-query* is 2nil*, a condition is signaled and then the user is queried. If 2si:record-source-file-name* returns 2nil*, it means that the user or a condition handler said the redefinition should not be performed. 3sys:fdefine-file-pathname* 1Variable* While the system is loading a file, this is the generic pathname for the file. The rest of the time it is 2nil*. 2fdefine* uses this to remember what file defines each function. 3si:get-source-file-name* 1function-spec* &optional 1type* Returns the generic pathname for the file in which 1function-spec* received a definition of type 1type*. If 1type* is 2nil*, the most recent definition is used, regardless of its type. 1function-spec* really is a function spec only if 1type* is 2defun*; for example, if 1type* is 2defvar*, 1function-spec* is a variable name. Other types that are used by the system are 2defflavor* and 2defstruct*. This function returns the generic pathname of the source file. To obtain the actual source file pathname, use the 2:source-pathname* operation (see ). A second value is returned, which is the type of the definition that was reported. 3si:get-all-source-file-names* 1function-spec* Returns a list describing the generic pathnames of all the definitions this function-spec has received, of all types. The list is an alist whose elements look like 3(1type* 1pathname*...) sys:redefinition* (sys:warning) 1Condition Flavor* This condition, which is not an error, is signaled by 2si:record-source-file-name* when something is redefined by a different file. The handler for this condition can control what is done about the redefinition. The condition instance provides the operations 2:name*, 2:definition-type*, 2:old-pathname* and 2:new-pathname*. 2:name* and 2:definition-type* return the 1name* and 1type* arguments to 2si:record-source-file-name*. 2:old-pathname* and 2:new-pathname* return two generic pathnames saying where the old definition was and where this one is. The new pathname may be 2nil*, meaning that the redefinition is being done by the user, not in any file. Two proceed types are available, 2:proceed* and 2:inhibit-definition*. The first tells 2si:record-source-file-name* to return 2t*, the second tells it to return 2nil*. If the condition is not handled at all, the user is queried or warned according to the value of 2inhibit-fdefine-warnings*. 3inhibit-fdefine-warnings* 1Variable* This variable is normally 2nil*. Setting it to 2t* prevents 2si:record-source-file-name* from warning you and asking about questionable redefinitions such as a function being redefined by a different file than defined it originally, or a symbol that belongs to one package being defined by a file that belongs to a different package. Setting it to 2:just-warn* allows the warnings to be printed out, but prevents the queries from happening; it assumes that your answer is `yes', i.e. that it is all right to redefine the function. 3fset-carefully* 1symbol* 1definition* &optional 1force-flag* This function is obsolete. It is equivalent to 3(fdefine 1symbol* 1definition* t 1force-flag*) fdefinedp* 1function-spec* This returns 2t* if 1function-spec* has a definition, 2nil* if it does not. 3fdefinition* 1function-spec* This returns 1function-spec*'s definition. If it has none, an error occurs. 3fdefinition-location* 1function-spec* Equivalent to 2(locf (fdefinition 1function-spec*))*. For some kinds of function specs, though not for symbols, this (whichever way you write it) can cause data structure to be created to hold a definition. For example, if 1function-spec* is of the 2:property* kind, then an entry may have to be added to the property list if it isn't already there. 3fundefine* 1function-spec* Makes 1function-spec* undefined; the cell where its definition is stored becomes void. For symbols this is equivalent to 2fmakunbound*. If the function is encapsulated, 2fundefine* removes both the basic definition and the encapsulations. Some types of function specs (2:location* for example) do not implement 2fundefine*. 2fundefine* on a 2:within* function spec removes the replacement of 1function-to-affect*, putting the definition of 1within-function* back to its normal state. 2fundefine* on a 2:method* function spec removes the method completely, so that future messages will be handled by some other method (see the flavor chapter). 3undefun* 1function-spec* If 1function-spec* has a saved previous basic definition, this interchanges the current and previous basic definitions, leaving the encapsulations alone. If 1function-spec* has no saved previous definition, 2undefun* asks the user whether to make it undefined. This undoes the effect of redefining a function. See also 2uncompile* (4(COMPILER-1)How to Invoke the Compiler*). 3si:function-spec-get* 1function-spec* 1indicator* Returns the value of the 1indicator* property of 1function-spec*, or 2nil* if it doesn't have such a property. 3si:function-spec-putprop* 1function-spec* 1value* 1indicator* Gives 1function-spec* an 1indicator* property whose value is 1value*. 3si:function-spec-lessp* 1function-spec1* 1function-spec2* Compares the two function specs with an ordering that is useful in sorting lists of function specs for presentation to the user. 3si:function-parent* 1function-spec* If 1function-spec* does not have its own definition, textually speaking, but is defined as part of the definition of something else, this function returns the function spec for that something else. For example, if 1function-spec* is an accessor function for a 2defstruct*, the value returned is the name of the 2defstruct*. The intent is that if the caller has not been able to find the definition of 1function-spec* in a more direct fashion, it can try looking for the definition of the 1function-parent* of 1function-spec*. This is used by the editor's 2Meta-.* command. 3sys:invalid-function-spec* (3error*) 1Condition* This condition name belongs to the error signaled when you refer to a function spec that is syntactically invalid; such as, if it is a list whose car is not a recognized type of function spec. The condition object supports the operation 2:function-spec*, which returns the function spec which was invalid. Note that in a few cases the condition 2:wrong-type-argument* is signaled instead. These are the cases in which the error is correctable. =Node: How Programs Examine Functions =Text: 3HOW PROGRAMS EXAMINE FUNCTIONS* These functions take a function as argument and return information about that function. Some also accept a function spec and operate on its definition. The others do not accept function specs in general but do accept a symbol as standing for its definition. (Note that a symbol is a function as well as a function spec). The function 2documentation* can be used to examine a function's documentation string. See 4(MISCELL-1)Documentation*. 3debugging-info* 1function* This returns the debugging info alist of 1function*, or 2nil* if it has none. 3arglist* 1function* &optional 1real-flag* 2arglist* is given a function or a function spec, and returns its best guess at the nature of the function's lambda-list. It can also return a second value which is a list of descriptive names for the values returned by the function. If 1function* is a symbol, 2arglist* of its function definition is used. If the 1function* is an actual 2lambda*-expression, its cadr, the lambda-list, is returned. But if 1function* is compiled, 2arglist* attempts to reconstruct the lambda-list of the original definition, using whatever debugging information was saved by the compiler. Some functions' real argument lists are not what would be most descriptive to a user. A function may take a rest argument for technical reasons even though there are standard meanings for the first elements of that argument. For such cases, the definition of the function can specify, with a local declaration, a value to be returned when the user asks about the argument list. Example: 3(defun foo (&rest rest-arg)* 3 (declare (arglist x y &rest z))* 3 .....)* 1real-flag* has one of three values: 2nil* Return the arglist declared by the user in preference to the actual one. 2t* Return the actual arglist as computed from the function definition's handling of arguments, ignoring any 2arglist* declaration. For a compiled function, this omits all keyword arguments (replacing them with a rest argument) and may replace initial values of optional arguments with 2si:*hairy** if the actual expressions are too complicated. 2compile* Like 2nil*, but in the case of a compiled function it returns the actual arglist of the lambda-expression that was originally compiled. The compiler uses this as a basis for checking for incorrect calls to the function. Programs interested in how many and what kind (evaluated or quoted) of arguments to pass should use 2args-info* instead. When a function returns multiple values, it is useful to give the values names so that the caller can be reminded which value is which. By means of a 2return-list* declaration in the function's definition, entirely analogous to the 2arglist* declaration above, you can specify a list of mnemonic names for the returned values. This list is then returned by 2arglist* as the second value. 3(arglist 'arglist)* 3 => (function &optional real-flag) 2and* (arglist return-list) function-name* 1function* &optional 1try-flavor-name* Returns the name of the function 1function*, if that can be determined. If 1function* does not describe what its name is, 1function* itself is returned. If 1try-flavor-name* is non-2nil*, then if 1function* is a flavor instance (which can, after all, be used as a function), then the flavor name is returned. If the optional argument is 2nil*, flavor instances are treated as anonymous. 3eh:arg-name* 1function* 1arg-number* Returns the name of argument number 1arg-number* in function 1function*. Returns 2nil* if the function doesn't have such an argument, or if the name is not recorded. 2&rest* arguments are not obtained with 2arg-number*; use 2rest-arg-name* to obtain the name of 1function*'s 2&rest* argument, if any. 3eh:rest-arg-name* 1function* Returns the name of the rest argument of function 1function*, or 2nil* if 1function* does not have one. 3eh:local-name* 1function* 1local-number* Returns the name of local variable number 1local-number* in function 1function*. If 1local-number* is zero, this gets the name of the rest arg in any function that accepts a rest arg. Returns 2nil* if the function doesn't have such a local. 3args-info* 1function* Returns a fixnum called the ``numeric argument descriptor'' of the 1function*, which describes the way the function takes arguments. This descriptor is used internally by the microcode, the evaluator, and the compiler. 1function* can be a function or a function spec. The information is stored in various bits and byte fields in the fixnum, which are referenced by the symbolic names shown below. By the usual Lisp Machine convention, those starting with a single `2%*' are bit-masks (meant to be 2logand*'ed or 2bit-test*'ed with the number), and those starting with `2%%*' are byte specifiers, meant to be used with 2ldb* or 2ldb-test*. Here are the fields: 2%%arg-desc-min-args* 'vindex %%arg-desc-min-args This is the minimum number of arguments that may be passed to this function, i.e. the number of required parameters. 2%%arg-desc-max-args* 'vindex %%arg-desc-max-args This is the maximum number of arguments that may be passed to this function, i.e. the sum of the number of required parameters and the number of optional parameters. If there is a rest argument, this is not really the maximum number of arguments that may be passed; an arbitrarily-large number of arguments is permitted, subject to limitations on the maximum size of a stack frame (about 200 words). 2%arg-desc-evaled-rest* 'vindex %arg-desc-evaled-rest If this bit is set, the function has a rest argument, and it is not quoted. 2%arg-desc-quoted-rest* 'vindex %arg-desc-quoted-rest If this bit is set, the function has a rest argument, and it is quoted. Most special forms have this bit. 2%arg-desc-fef-quote-hair* 'vindex %arg-desc-fef-quote-hair If this bit is set, there are some quoted arguments other than the rest argument (if any), and the pattern of quoting is too complicated to describe here. The ADL (Argument Description List) in the FEF should be consulted. This is only for special forms. 2%arg-desc-interpreted* 'vindex %arg-desc-interpreted This function is not a compiled-code object, and a numeric argument descriptor cannot be computed. Usually 2args-info* does not return this bit, although 2%args-info* does. 2%arg-desc-fef-bind-hair* 'vindex %arg-desc-fef-bind-hair There is argument initialization, or something else too complicated to describe here. The ADL (Argument Description List) in the FEF should be consulted. Note that 2%arg-desc-quoted-rest* and 2%arg-desc-evaled-rest* cannot both be set. 3%args-info* 1function* This is an internal function; it is like 2args-info* but does not work for interpreted functions. Also, 1function* must be a function, not a function spec. It exists because it has to be in the microcode anyway, for 2apply* and the basic function-calling mechanism. =Node: Encapsulations =Text: 3ENCAPSULATIONS* The definition of a function spec actually has two parts: the 1basic definition*, and 1encapsulations*. The basic definition is what is created by functions like 2defun*, and encapsulations are additions made by 2trace* or 2advise* to the basic definition. The purpose of making the encapsulation a separate object is to keep track of what was made by 2defun* and what was made by 2trace*. If 2defun* is done a second time, it replaces the old basic definition with a new one while leaving the encapsulations alone. Only advanced users should ever need to use encapsulations directly via the primitives explained in this section. The most common things to do with encapsulations are provided as higher-level, easier-to-use features: 2trace* (see 4(DEBUGGING-5)Tracing Function Execution*), 2breakon* (see 4(DEBUGGING-5)Breakon*) and 2advise* (see 4(DEBUGGING-5)Advising a Function*). The actual definition of the function spec is the outermost encapsulation; this contains the next encapsulation, and so on. The innermost encapsulation contains the basic definition. The way this containing is done is as follows. An encapsulation is actually a function whose debugging info alist contains an element of the form 3(si:encapsulated-definition 1uninterned-symbol* 1encapsulation-type*)* The presence of such an element in the debugging info alist is how you recognize a function to be an encapsulation. An encapsulation is usually an interpreted function (a list starting with 2named-lambda*) but it can be a compiled function also, if the application which created it wants to compile it. 1uninterned-symbol*'s function definition is the thing that the encapsulation contains, usually the basic definition of the function spec. Or it can be another encapsulation, which has in it another debugging info item containing another uninterned symbol. Eventually you get to a function which is not an encapsulation; it does not have the sort of debugging info item which encapsulations all have. That function is the basic definition of the function spec. Literally speaking, the definition of the function spec is the outermost encapsulation, period. The basic definition is not the definition. If you are asking for the definition of the function spec because you want to apply it, the outermost encapsulation is exactly what you want. But the basic definition can be found mechanically from the definition, by following the debugging info alists. So it makes sense to think of it as a part of the definition. In regard to the function-defining special forms such as 2defun*, it is convenient to think of the encapsulations as connecting between the function spec and its basic definition. An encapsulation is created with the macro 2si:encapsulate*. 3si:encapsulate* 1Macro* A call to 2si:encapsulate* looks like 3(si:encapsulate 1function-spec* 1outer-function* 1type** 3 1body-form** 3 1extra-debugging-info*)* All the subforms of this macro are evaluated. In fact, the macro could almost be replaced with an ordinary function, except for the way 1body-form* is handled. 1function-spec* evaluates to the function spec whose definition the new encapsulation should become. 1outer-function* is another function spec, which should often be the same one. Its only purpose is to be used in any error messages from 2si:encapsulate*. 1type* evaluates to a symbol which identifies the purpose of the encapsulation and says what the application is. For example, that could be 2advise* or 2trace*. The list of possible types is defined by the system because encapsulations are supposed to be kept in an order according to their type (see 2si:encapsulation-standard-order*, 4(FUNCTIONS-2)Encapsulations*). 1type* should have an 2si:encapsulation-grind-function* property which tells 2grindef* what to do with an encapsulation of this type. 1body-form* evaluates to the body of the encapsulation-definition, the code to be executed when it is called. Backquote is typically used for this expression; see 4(MACROS-1)Backquote*. 2si:encapsulate* is a macro because, while 1body* is being evaluated, the variable 2si:encapsulated-function* is bound to a list of the form 2(function 1uninterned-symbol*)*, referring to the uninterned symbol used to hold the prior definition of 1function-spec*. If 2si:encapsulate* were a function, 1body-form* would just get evaluated normally by the evaluator before 2si:encapsulate* ever got invoked, and so there would be no opportunity to bind 2si:encapsulated-function*. The form 1body-form* should contain 2`(apply* 2,si:encapsulated-function arglist)* somewhere if the encapsulation is to live up to its name and truly serve to encapsulate the original definition. (The variable 2arglist* is bound by some of the code which the 2si:encapsulate* macro produces automatically. When the body of the encapsulation is run 2arglist*'s value will be the list of the arguments which the encapsulation received.) 1extra-debugging-info* evaluates to a list of extra items to put into the debugging info alist of the encapsulation function (besides the one starting with 2si:encapsulated-definition*, which every encapsulation must have). Some applications find this useful for recording information about the encapsulation for their own later use. If 2compile-encapsulations-flag* is non-2nil*, the encapsulation is compiled before it is installed. The encapsulations on a particular function spec can be compiled by calling 2compile-encapsulations*. See 4(COMPILER-1)How to Invoke the Compiler*. Compiled encapsulations can still be unencapsulated since the information needed to do so is stored in the debugging info alist, which is preserved by compilation. However, applications which wish to modify the code of the encapsulations they previously created must check for encapsulations that have been compiled and uncompile them. This can be done by finding the 2sys:interpreted-definition* entry in the debugging info alist, which is present in all compiled functions except those made by file-to-file compilation. When a special function is encapsulated, the encapsulation is itself a special function with the same argument quoting pattern. Therefore, when the outermost encapsulation is started, each argument has been evaluated or not as appropriate. Because each encapsulation calls the prior definition with 2apply*, no further evaluation takes place, and the basic definition of the special form also finds the arguments evaluated or not as appropriate. The basic definition may call 2eval* on some of these arguments or parts of them; the encapsulations should not. Macros cannot be encapsulated, but their expander functions can be; if the definition of 1function-spec* is a macro, then 2si:encapsulate* automatically encapsulates the expander function instead. In this case, the definition of the uninterned symbol is the original macro definition, not just the original expander function. It would not work for the encapsulation to apply the macro definition. So during the evaluation of 1body-form*, 2si:encapsulated-function* is bound to the form 2(cdr (function 1uninterned-symbol*))*, which extracts the expander function from the prior definition of the macro. Because only the expander function is actually encapsulated, the encapsulation does not see the evaluation or execution of the expansion itself. The value returned by the encapsulation is the expansion of the macro call, not the value computed by the expansion. A program which creates encapsulations often needs to examine an encapsulation it created and find the body. For example, adding a second piece of advice to one function requires doing this. The proper way to do it is to use 2si:encapsulation-body*. 3si:encapsulation-body* 1encapsulation* Returns a list whose car is the body-form of 1encapsulation*. It is the form that was the fourth argument of 2si:encapsulate* when 1encapsulation* was created. To illustrate this relationship, 3(si:encapsulate 'foo 'foo 'trace 'body))* 3(si:encapsulation-body (fdefinition 'foo))* 3 => (body)* It is possible for one function to have multiple encapsulations, created by different subsystems. In this case, the order of encapsulations is independent of the order in which they were made. It depends instead on their types. All possible encapsulation types have a total order and a new encapsulation is put in the right place among the existing encapsulations according to its type and their types. 3si:encapsulation-standard-order* 1Variable* The value of this variable is a list of the allowed encapsulation types, in the order in which the encapsulations are supposed to be kept (innermost encapsulations first). If you want to add new kinds of encapsulations, you should add another symbol to this list. Initially its value is 3(advise breakon trace si:rename-within)* 2advise* encapsulations are used to hold advice (see 4(DEBUGGING-5)Advising a Function*). 2breakon* encapsulations are used for implementing 2breakon* (see 4(DEBUGGING-5)Breakon*). 2trace* encapsulations are used for implementing tracing (see 4(DEBUGGING-5)Tracing Function Execution*). 2si:rename-within* encapsulations are used to record the fact that function specs of the form 2(:within 1within-function* 1altered-function*)* have been defined. The encapsulation goes on 1within-function* (see 4(FUNCTIONS-2)Rename-Within Encapsulations* for more information). Every symbol used as an encapsulation type must be on the list 2si:encapsulation-standard-order*. In addition, it should have an 2si:encapsulation-grind-function* property whose value is a function that 2grindef* will call to process encapsulations of that type. This function need not take care of printing the encapsulated function because 2grindef* will do that itself. But it should print any information about the encapsulation itself which the user ought to see. Refer to the code for the grind function for 2advise* to see how to write one. To find the right place in the ordering to insert a new encapsulation, it is necessary to parse existing ones. This is done with the function 2si:unencapsulate-function-spec*. 3si:unencapsulate-function-spec* 1function-spec* &optional 1encapsulation-types* This takes one function spec and returns another. If the original function spec is undefined, or has only a basic definition (that is, its definition is not an encapsulation), then the original function spec is returned unchanged. If the definition of 1function-spec* is an encapsulation, then its debugging info is examined to find the uninterned symbol that holds the encapsulated definition and the encapsulation type. If the encapsulation is of a type that is to be skipped over, the uninterned symbol replaces the original function spec and the process repeats. The value returned is the uninterned symbol from inside the last encapsulation skipped. This uninterned symbol is the first one that does not have a definition that is an encapsulation that should be skipped. Or the value can be 1function-spec* if 1function-spec*'s definition is not an encapsulation that should be skipped. The types of encapsulations to be skipped over are specified by 1encapsulation-types*. This can be a list of the types to be skipped, or 2nil* meaning skip all encapsulations (this is the default). Skipping all encapsulations means returning the uninterned symbol that holds the basic definition of 1function-spec*. That is, the 1definition* of the function spec returned is the 1basic definition* of the function spec supplied. Thus, 3(fdefinition (si:unencapsulate-function-spec 'foo))* returns the basic definition of 2foo*, and 3(fdefine (si:unencapsulate-function-spec 'foo) 'bar)* sets the basic definition (just like using 2fdefine* with 1carefully* supplied as 2t*). 1encapsulation-types* can also be a symbol, which should be an encapsulation type; then we skip all types that are supposed to come outside of the specified type. For example, if 1encapsulation-types* is 2trace*, then we skip all types of encapsulations that come outside of 2trace* encapsulations, but we do not skip 2trace* encapsulations themselves. The result is a function spec that is where the 2trace* encapsulation ought to be, if there is one. Either the definition of this function spec is a 2trace* encapsulation, or there is no 2trace* encapsulation anywhere in the definition of 1function-spec*, and this function spec is where it would belong if there were one. For example, 3(let ((tem (si:unencapsulate-function-spec spec 'trace)))* 3 (and (eq tem (si:unencapsulate-function-spec tem '(trace)))* 3 (si:encapsulate tem spec 'trace `(...1body*...))))* finds the place where a 2trace* encapsulation ought to go and makes one unless there is already one there. 3(let ((tem (si:unencapsulate-function-spec spec 'trace)))* 3 (fdefine tem (fdefinition (si:unencapsulate-function-spec* 3 tem '(trace)))))* eliminates any 2trace* encapsulation by replacing it by whatever it encapsulates. (If there is no 2trace* encapsulation, this code changes nothing.) These examples show how a subsystem can insert its own type of encapsulation in the proper sequence without knowing the names of any other types of encapsulations. Only the variable 2si:encapsulation-standard-order*, which is used by 2si:unencapsulate-function-spec*, knows the order. =Node: Rename-Within Encapsulations =Text: 3RENAME-WITHIN ENCAPSULATIONS* One special kind of encapsulation is the type 2si:rename-within*. This encapsulation goes around a definition in which renamings of functions have been done. How is this used? If you define, advise, or trace 2(:within foo bar)*, then 2bar* gets renamed to 2#:altered-bar-within-foo* wherever it is called from 2foo*, and 2foo* gets a 2si:rename-within* encapsulation to record the fact. The purpose of the encapsulation is to enable various parts of the system to do what seems natural to the user. For example, 2grindef* (see 4(READPRINT-3)Pretty-Printing Output Functions*) notices the encapsulation, and so knows to print 2bar* instead of 2#:altered-bar-within-foo* when grinding the definition of 2foo*. Also, if you redefine 2foo*, or trace or advise it, the new definition gets the same renaming done (2bar* replaced by 2#:altered-bar-within-foo*). To make this work, everyone who alters part of a function definition should pass the new part of the definition through the function 2si:rename-within-new-definition-maybe*. 3si:rename-within-new-definition-maybe* 1function-spec* 1new-structure* Given 1new-structure*, which is going to become a part of the definition of 1function-spec*, perform on it the replacements described by the 2si:rename-within* encapsulation in the definition of 1function-spec*, if there is one. The altered (copied) list structure is returned. It is not necessary to call this function yourself when you replace the basic definition because 2fdefine* with 1carefully* supplied as 2t* does it for you. 2si:encapsulate* does this to the body of the new encapsulation. So you only need to call 2si:rename-within-new-definition-maybe* yourself if you are rplac'ing part of the definition. For proper results, 1function-spec* must be the outer-level function spec. That is, the value returned by 2si:unencapsulate-function-spec* is 1not* the right thing to use. It will have had one or more encapsulations stripped off, including the 2si:rename-within* encapsulation if any, and so no renamings will be done.