Common Lisp the Language, 2nd Edition
Next: Declarations
Up: Macros
Previous: Compiler
Macros
X3J13 voted in June 1989 (SYNTACTIC-ENVIRONMENT-ACCESS) 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 specifiers, with the exception of
special
, can be defined fairly easily using
define-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
(DESTRUCTURING-BIND) to add destructuring-bind
to the
language. However, parse-macro
is worth having anyway,
since any program-analyzing program is going to need to define it, and
the implementation isn’t completely trivial even with
destructuring-bind
to build upon.
The function enclose
allows expander functions to be
defined in a non-null lexical environment, as required by the vote of
X3J13 in March 1989 (DEFINING-MACROS-NON-TOP-LEVEL) . 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 (EVAL-WHEN-NON-TOP-LEVEL) ).
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 definitions 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 effect 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 first value indicates the type of definition or binding for variable in env:
nil
There is no apparent definition or binding for variable.
:special
The variable refers to a special variable, either declared or
proclaimed.
:lexical
The variable refers to a lexical variable.
:symbol-macro
The variable refers to a symbol-macrolet
binding.
:constant
Either the variable refers to a named constant defined by
defconstant
or the variable is a keyword
symbol.
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 specifiers, 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:
dynamic-extent
A non-nil
value indicates that the variable has
been declared dynamic-extent
. If the value is
nil
, the pair might be omitted.
ignore
A non-nil
value indicates that the variable has
been declared ignore
. If the value is nil
, the
pair might be omitted.
type
The value is a type specifier associated with the variable by a
type
declaration or an abbreviated declaration such as
(fixnum
variable
)
. If no
explicit association exists, either by proclaim
or
declare
, then the type specifier is t
. It is
permissible for implementations to use a type specifier that is
equivalent to or a supertype of the one appearing in the original
declaration. If the value is t
, the pair might be
omitted.
If an implementation supports additional declaration specifiers 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 defined 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 define-declaration
) are undefined.
Note that the global binding might differ 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 first value indicates the type of definition or binding of the function-name which is apparent in env:
nil
There is no apparent definition for function.
:function
The function refers to a function.
:macro
The function refers to a macro.
:special-form
The function refers to a special form.
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 first value.
The second value specifies whether the definition is local or global.
If local, the second value is true; it is nil
when the
definition 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 specifiers, 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:
dynamic-extent
A non-nil
value indicates that the function has been
declared dynamic-extent
. If the value is nil
,
the pair might be omitted.
inline
The value is one of the symbols inline
,
notinline
, or nil
to indicate whether the
function-name has been declared inline
, declared
notinline
, or neither, respectively. If the value is
nil
, the pair might be omitted.
ftype
The value is the type specifier associated with the function-name in the
environment, or the symbol function
if there is no
functional type declaration or proclamation associated with the
function-name. This value might not include all the apparent
ftype
declarations for the function-name. It is permissible
for implementations to use a type specifier that is equivalent to or a
supertype of the one that appeared in the original declaration. If the
value is function
, the pair might be omitted.
If an implementation supports additional declaration specifiers 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 defined 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 first 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 define-declaration
) are undefined.
Note that the global binding might differ 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:
optimize
A single value is returned, a list whose entries are of the form
(
quality
value
)
,
where quality is one of the standard optimization qualities
(speed
, safety
,
compilation-speed
, space
, debug)
or some implementation-specific optimization quality, and value
is an integer in the range 0 to 3 (inclusive). The returned list always
contains an entry for each of the standard qualities and for each of the
implementation-specific qualities. In the absence of any previous
declarations, the associated values are implementation-dependent. The
list might contain multiple entries for a quality, in which case the
first such entry specifies the current value. The consequences of
destructively modifying this list or its elements are undefined.
declaration
A single value is returned, a list of the declaration names that have
been proclaimed as valid through the use of the declaration
proclamation. The consequences of destructively modifying this list or
its elements are undefined.
If an implementation is extended to recognize additional declaration
specifiers 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
specifier. If declaration-information
is used to return the
information, the corresponding decl-name must not be a symbol
that is external in any package defined 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.
:variable
The argument is a list of symbols that will be visible as bound
variables in the new environment. Whether each binding is to be
interpreted as special or lexical depends on special
declarations recorded in the environment or provided in the
:declare
argument.
:symbol-macro
The argument is a list of symbol macro definitions, each of the form
(
name
definition
)
;
that is, the argument is in the same format as the cadr of a
symbol-macrolet
special form. The new environment will have
local symbol-macro bindings of each symbol to the corresponding
expansion, so that macroexpand
will be able to expand them
properly. A type declaration in the :declare
argument that
refers to a name in this list implicitly modifies the definition
associated with the name. The effect is to wrap a the
form
mentioning the type around the definition.
:function
The argument is a list of function-names that will be visible as local
function bindings in the new environment.
:macro
The argument is a list of local macro definitions, each of the form
(
name
definition
)
.
Note that the argument is not in the same format as the
cadr of a macrolet
special form. Each
definition must be a function of two arguments (a form and an
environment). The new environment will have local macro bindings of each
name to the corresponding expander function, which will be returned by
macro-function
and used by macroexpand
.
:declare
The argument is a list of declaration specifiers. Information about
these declarations can be retrieved from the resulting environment using
variable-information
, function-information
,
and declaration-information
.
The consequences of subsequently destructively modifying the list structure of any of the arguments to this function are undefined.
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 specifier 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 modified.
While an environment argument received by an *evalhook*
function is permitted to be used as the environment argument to
augment-environment
, the consequences are undefined 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 defined in
this section and functions such as macroexpand
.
[Macro]
define-declaration
decl-name
lambda-list
{
form
}*
This macro defines a handler for the named declaration. It is the
mechanism by which augment-environment
is extended to
support additional declaration specifiers. The function defined by this
macro will be called with two arguments, a declaration specifier whose
car is decl-name and the env argument to
augment-environment
. This function must return two values.
The first value must be one of the following keywords:
:variable
The declaration applies to variable bindings.
:function
The declaration applies to function bindings.
:declare
The declaration does not apply to bindings.
If the first 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 specified key.
If the first 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.
define-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 specifiers, the evaluator and
compiler are permitted, but not required, to add information about
declaration specifiers defined with define-declaration
to
the macro expansion and *evalhook*
environments.
The consequences are undefined if decl-name is a symbol that can appear as the car of any standard declaration specifier.
The consequences are also undefined if the return value from a
declaration handler defined with define-declaration
includes a key name that is used by the corresponding accessor
to return information about any standard declaration specifier. (For
example, if the first return value from the handler is
:variable
, the second return value may not use the symbols
dynamic-extent
, ignore
, or type
as key names.)
The define-declaration
macro does not have any special
compile-time side effects (see section 25.1).
[Function]
parse-macro
name
lambda-list
body
&optional
env
This function is used to process a macro definition 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
definition.
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,
specifically declarations and the definitions of macros and symbol
macros. The consequences are undefined 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.
Next: Declarations
Up: Macros
Previous: Compiler
Macros
AI.Repository@cs.cmu.edu