X3J13 voted in June 1989 to add some facilities for obtaining information from environment objects of the kind received as arguments by macro expansion functions, *macroexpand-hook* functions, and *evalhook* functions. There is a minimal set of accessors (variable-information, function-information, and declaration-information) and a constructor (augment-environment) for environments.
All of the standard declaration speciﬁers, with the exception of special, can be deﬁned fairly easily using deﬁne-declaration. It also seems to be able to handle most extended declarations.
The function parse-macro is provided so that users don’t have to write their own code to destructure macro arguments. This function is not entirely necessary since X3J13 voted in March 1989 to add destructuring-bind to the language. However, parse-macro is worth having anyway, since any program-analyzing program is going to need to deﬁne it, and the implementation isn’t completely trivial even with destructuring-bind to build upon.
The function enclose allows expander functions to be deﬁned in a non-null lexical environment, as required by the vote of X3J13 in March 1989 . It also provides a mechanism by which a program processing the body of an (eval-when (:compile-toplevel) ...) form can execute it in the enclosing environment (see issue ).
In all of these functions the argument named env is an environment object. (It is not required that implementations provide a distinguished representation for such objects.) Optional env arguments default to nil, which represents the local null lexical environment (containing only global deﬁnitions and proclamations that are present in the run-time environment). All of these functions should signal an error of type type-error if the value of an environment argument is not a syntactic environment object.
The accessor functions variable-information, function-information, and declaration-information retrieve information about declarations that are in eﬀect in the environment. Since implementations are permitted to ignore declarations (except for special declarations and optimize safety declarations if they ever compile unsafe code), these accessors are required only to return information about declarations that were explicitly added to the environment using augment-environment. They might also return information about declarations recognized and added to the environment by the interpreter or the compiler, but that is at the discretion of the implementor. Implementations are also permitted to canonicalize declarations, so the information returned by the accessors might not be identical to the information that was passed to augment-environment.
[Function]variable-information variable &optional env
This function returns information about the interpretation of the symbol variable when it appears as a variable within the lexical environment env. Three values are returned.
The ﬁrst value indicates the type of deﬁnition or binding for variable in env:
The second value indicates whether there is a local binding of the name. If the name is locally bound, the second value is true; otherwise, the second value is nil.
The third value is an a-list containing information about declarations that apply to the apparent binding of the variable. The keys in the a-list are symbols that name declaration speciﬁers, and the format of the corresponding value in the cdr of each pair depends on the particular declaration name involved. The standard declaration names that might appear as keys in this a-list are:
If an implementation supports additional declaration speciﬁers that apply to variable bindings, those declaration names might also appear in the a-list. However, the corresponding key must not be a symbol that is external in any package deﬁned in the standard or that is otherwise accessible in the common-lisp-user package.
The a-list might contain multiple entries for a given key. The consequences of destructively modifying the list structure of this a-list or its elements (except for values that appear in the a-list as a result of deﬁne-declaration) are undeﬁned.
Note that the global binding might diﬀer from the local one and can be retrieved by calling variable-information with a null lexical environment.
[Function]function-information function &optional env
This function returns information about the interpretation of the function-name function when it appears in a functional position within lexical environment env. Three values are returned.
The ﬁrst value indicates the type of deﬁnition or binding of the function-name which is apparent in env:
Some function-names can refer to both a global macro and a global special form. In such a case the macro takes precedence and :macro is returned as the ﬁrst value.
The second value speciﬁes whether the deﬁnition is local or global. If local, the second value is true; it is nil when the deﬁnition is global.
The third value is an a-list containing information about declarations that apply to the apparent binding of the function. The keys in the a-list are symbols that name declaration speciﬁers, and the format of the corresponding values in the cdr of each pair depends on the particular declaration name involved. The standard declaration names that might appear as keys in this a-list are:
If an implementation supports additional declaration speciﬁers that apply to function bindings, those declaration names might also appear in the a-list. However, the corresponding key must not be a symbol that is external in any package deﬁned in the standard or that is otherwise accessible in the common-lisp-user package.
The a-list might contain multiple entries for a given key. In this case the value associated with the ﬁrst entry has precedence. The consequences of destructively modifying the list structure of this a-list or its elements (except for values that appear in the a-list as a result of deﬁne-declaration) are undeﬁned.
Note that the global binding might diﬀer from the local one and can be retrieved by calling function-information with a null lexical environment.
[Function]declaration-information decl-name &optional env
This function returns information about declarations named by the symbol decl-name that are in force in the environment env. Only declarations that do not apply to function or variable bindings can be accessed with this function. The format of the information that is returned depends on the decl-name involved.
It is required that this function recognize optimize and declaration as decl-names. The values returned for these two cases are as follows:
If an implementation is extended to recognize additional declaration speciﬁers in declare or proclaim, it is required that either the declaration-information function should recognize those declarations also or the implementation should provide a similar accessor that is specialized for that declaration speciﬁer. If declaration-information is used to return the information, the corresponding decl-name must not be a symbol that is external in any package deﬁned in the standard or that is otherwise accessible in the common-lisp-user package.
[Function]augment-environment env &key :variable :symbol-macro :function :macro :declare
This function returns a new environment containing the information present in env augmented with the information provided by the keyword arguments. It is intended to be used by program analyzers that perform a code walk.
The arguments are supplied as follows.
The consequences of subsequently destructively modifying the list structure of any of the arguments to this function are undeﬁned.
An error is signaled if any of the symbols naming a symbol macro in the :symbol-macro argument is also included in the :variable argument. An error is signaled if any symbol naming a symbol macro in the :symbol-macro argument is also included in a special declaration speciﬁer in the :declare argument. An error is signaled if any symbol naming a macro in the :macro argument is also included in the :function argument. The condition type of each of these errors is program-error.
The extent of the returned environment is the same as the extent of the argument environment env. The result might share structure with env but env is not modiﬁed.
While an environment argument received by an *evalhook* function is permitted to be used as the environment argument to augment-environment, the consequences are undeﬁned if an attempt is made to use the result of augment-environment as the environment argument for evalhook. The environment returned by augment-environment can be used only for syntactic analysis, that is, as an argument to the functions deﬁned in this section and functions such as macroexpand.
This macro deﬁnes a handler for the named declaration. It is the mechanism by which augment-environment is extended to support additional declaration speciﬁers. The function deﬁned by this macro will be called with two arguments, a declaration speciﬁer whose car is decl-name and the env argument to augment-environment. This function must return two values. The ﬁrst value must be one of the following keywords:
If the ﬁrst value is :variable or :function then the second value must be a list, the elements of which are lists of the form (binding-name key value). If the corresponding information function (either variable-information or function-information) is applied to the binding-name and the augmented environment, the a-list returned by the information function as its third value will contain the value under the speciﬁed key.
If the ﬁrst value is :declare, the second value must be a cons of the form (key . value). The function declaration-information will return value when applied to the key and the augmented environment.
deﬁne-declaration causes decl-name to be proclaimed to be a declaration; it is as if its expansion included a call (proclaim ’(declaration decl-name)). As is the case with standard declaration speciﬁers, the evaluator and compiler are permitted, but not required, to add information about declaration speciﬁers deﬁned with deﬁne-declaration to the macro expansion and *evalhook* environments.
The consequences are undeﬁned if decl-name is a symbol that can appear as the car of any standard declaration speciﬁer.
The consequences are also undeﬁned if the return value from a declaration handler deﬁned with deﬁne-declaration includes a key name that is used by the corresponding accessor to return information about any standard declaration speciﬁer. (For example, if the ﬁrst return value from the handler is :variable, the second return value may not use the symbols dynamic-extent, ignore, or type as key names.)
[Function]parse-macro name lambda-list body &optional env
This function is used to process a macro deﬁnition in the same way as defmacro and macrolet. It returns a lambda-expression that accepts two arguments, a form and an environment. The name, lambda-list, and body arguments correspond to the parts of a defmacro or macrolet deﬁnition.
The lambda-list argument may include &environment and &whole and may include destructuring. The name argument is used to enclose the body in an implicit block and might also be used for implementation-dependent purposes (such as including the name of the macro in error messages if the form does not match the lambda-list).
[Function]enclose lambda-expression &optional env
This function returns an object of type function that is equivalent to what would be obtained by evaluating ‘(function ,lambda-expression) in a syntactic environment env. The lambda-expression is permitted to reference only the parts of the environment argument env that are relevant only to syntactic processing, speciﬁcally declarations and the deﬁnitions of macros and symbol macros. The consequences are undeﬁned if the lambda-expression contains any references to variable or function bindings that are lexically visible in env, any go to a tag that is lexically visible in env, or any return-from mentioning a block name that is lexically visible in env.