This library provides a uniform API, as specified in Common Lisp the Language 2, for accessing information in implementation-defined lexical environment objects. All major Common Lisp implementations are supported, even those which don’t support the CLTL2 environment access API.
On implementations, which provide the CLTL2 environment access API, this library is simply a wrapper which handles the peculiarities of each implementation.
ON implementations, which do not provide the CLTL2 environment access API, the environment information is extracted by code-walking the forms which modify the environment.
The following functions/macros, from the CLTL2 API, are provided by this library:
-
VARIABLE-INFORMATION
-
FUNCTION-INFORMATION
-
DECLARATION-INFORMATION
-
DEFINE-DECLARATION
-
AUGMENT-ENVIRONMENT
-
ENCLOSE
-
PARSE-MACRO
The environment access API is provided by the package
CL-ENVIRONMENTS.CLTL2
. The functions exported by this package can be
used directly, however they will not return meaningful information on
implementations which do not provide the CLTL2 API natively, unless
the forms which modify the environment are walked by the code walker.
The CL-ENVIRONMENTS-CL
package, nickname CL-ENVIRONMENTS
, is a
clone of the COMMON-LISP
package with the exception that it exports
the symbols in the CL-ENVIRONMENTS.CLTL2
package and all CL special
operators, which modify the environment, are shadowed with macros
which invoke the code walker. This package should be used, instead of
the COMMON-LISP
package, in order to be able to obtain accurate
information about the environment.
See Common Lisp the Language 2 for the Environments API specification. This library adheres to that specification as closely as possible.
Function: VARIABLE-INFORMATION SYMBOL &OPTIONAL ENV
Returns information about the variable binding for symbol SYMBOL
in
the lexical environment ENV
.
SYMBOL
-
The symbol for which the variable binding information is retrieved.
ENV
-
The environment from which to retrieve the binding information. Defaults to the
NIL
global environment if it is not provided.
Returns three values:
-
The binding type identified by one of the following symbols:
NIL
-
No apparent variable binding for
SYMBOL
inENV
:LEXICAL
-
SYMBOL
refers to a lexical variable. :SPECIAL
-
SYMBOL
refers to a special variable. :SYMBOL-MACRO
-
SYMBOL
refers to a symbol-macro. :CONSTANT
-
SYMBOL
refers to a constant, defined byDEFCONSTANT
, or is a keyword.
-
T
if there is a local variable binding forSYMBOL
,NIL
otherwise. -
An alist containing the declaration information applying to the variable.
Function: FUNCTION-INFORMATION SYMBOL &OPTIONAL ENV
Returns information about the function binding for SYMBOL
in the
environment ENV
.
SYMBOL
-
The symbol for which the function binding information is retrieved.
ENV
-
The environment from which to retrieve the binding information. Defaults to the global
NIL
environment if it is not provided.
Returns three values:
-
The binding type identified by one of the following symbols:
NIL
-
No apparent function binding for
SYMBOL
inENV
. :FUNCTION
-
SYMBOL
refers to a function. :MACRO
-
SYMBOL
refers to a macro. :SPECIAL-FORM
-
SYMBOL
refers to a special operator, which does not have an associated macro function.
-
T
if there is a local fucntion binding forSYMBOL
,NIL
otherwise. -
An alist containing the declaration information applying to the function.
Function: DECLARATION-INFORMATION NAME &OPTIONAL ENV
Returns information about declarations which neither apply to variables nor functions.
NAME
-
The declaration name.
ENV
-
The environment from which to retrieve the declaration information. Defaults to the global
NIL
environment if it is not provided.
Macro: DEFINE-DECLARATION NAME (ARG-VAR &OPTIONAL ENV-VAR) &BODY BODY
Define a handler for a custom (non-standard) declaration.
NAME
-
The name of the declaration for which to define a handler.
❗The name should not be the same as a standard CL declaration, nor an implementation-specific declaration. ARG-VAR
-
The name of the variable to which, the argument list of the declaration (the
CDR
of the declaration expression(NAME . ARGS)
) is bound. ENV-VAR
-
The name of the variable to which the lexical environment, in which the declaration occurs, is bound.
BODY
-
The forms comprising the body of the declaration handler function, in an implicit
PROGN
.
The declaration handler function should return two values:
-
A keyword identifying what the declaration applies to:
:VARIABLE
-
The declaration applies to variable bindings.
:FUNCTION
-
The declaration applies to function bindings.
:DECLARE
-
The declaration neither applies to variable nor function bindings.
-
The declaration information which should be added to the environment.
If the first value is either
:VARIABLE
or:FUNCTION
, the second value should be a list where each element is of the form(SYMBOL KEY VALUE)
whereSYMBOL
is theSYMBOL
naming the binding to which the declaration applies. TheCONS
(KEY . VALUE)
will be included in the alist returned byVARIABLE-INFORMATION
/FUNCTION-INFORMATION
for the symbolSYMBOL
.If the first value is
:DECLARE
the second value should be aCONS
of the form(KEY . VALUE)
.VALUE
will be returned byDECLARATION-INFORMATION
for the declaration namedKEY
.
Function: AUGMENT-ENVIRONMENT ENV &KEY :VARIABLE :SYMBOL-MACRO :FUNCTION :MACRO :DECLARE
Create a new environment by augmenting an existing environment with new information.
ENV
-
The existing environment to augment.
VARIABLE
-
List of symbols which will be bound as variables in the new environment.
SYMBOL-MACRO
-
List of symbol-macro definitions, that will be present in the new environment, each of the form
(NAME EXPANSION)
. FUNCTION
-
List of symbols which will be bound as functions in the new environment.
MACRO
-
List of macro definitions, that will be present in the new environment. Each item of this list should be of the form
(NAME MACRO-FUNCTION)
whereMACRO-FUNCTION
is a function of two arguments, the entire macro form and the implementation specific lexical environment in which the macro is expanded.💡A macro definition form can be converted to a function using the ENCLOSE-MACRO
function. DECLARE
-
List of declaration specifiers, as if by
DECLARE
. Information about these declarations will be included in the environment and can be retrieved usingVARIABLE-INFORMATION
,FUNCTION-INFORMATION
andDECLARATION-INFORMATION
.
Returns a new environment object.
❗
|
For this function to work correctly across all
implementations, it must be able to extract information about the
local bindings in the environment ENV . This means that on
implementations which do not support the CLTL2 API, all local binding
forms in ENV must have been walked by the code walker.
|
🔥
|
If this function is not provided natively by the
implementation, the object returned is not a native environment object
and is thus not suitable to be passed to built-in functions which take
such an argument. The CL-ENVIRONMENTS-CL package provides shadowed
definitions of all functions in the COMMON-LISP package, that accept
an environment parameter, which can be used with either a native
environment or an environment returned by AUGMENT-ENVIRONMENT .
|
Function: ENCLOSE LAMBDA-EXPRESSION &OPTIONAL ENVIRONMENT
Evaluate a lambda-expression in an environment and return the resulting function object.
|
The LAMBDA-EXPRESSION may reference local and global macro
and symbol-macro definitions in ENVIRONMENT , however the behaviour
is undefined if it references any local variable or function bindings
in the environment.
|
LAMBDA-EXPRESSION
-
The lambda-expression.
ENVIRONMENT
-
The environment.
Returns a function object.
❗
|
This function has the same limitations as
AUGMENT-ENVIRONMENT in that on implementations which do not support
the CLTL2 API, the local bindings in the environment must have been
walked, with the code-walker, in order for them to be known to this
function.
|
Function: PARSE-MACRO NAME LAMBDA-LIST BODY &OPTIONAL ENVIRONMENT
Parse a macro definition form (as found in MACROLET
or DEFMACRO
)
into a lambda-expression of two arguments, suitable for use as a macro
function.
The resulting lambda-expression can be converted into a function
object, suitable to be passed as a macro-function in the :MACRO
argument of AUGMENT-ENVIRONMENT
, with the ENCLOSE
function.
💡
|
The ENCLOSE-MACRO function combines PARSE-MACRO and ENCLOSE
into a single step.
|
NAME
-
The symbol naming the macro.
LAMBDA-LIST
-
The macro lambda-list.
BODY
-
The forms comprising the macro’s body.
ENVIRONMENT
-
The environment in which the definition is found.
ℹ️
|
Most implementations of this function, if not all, including the implementation provided by this library for compilers which don’t support CLTL2, don’t expand macros in the macro body. Thus don’t rely on this function to return a fully macro-expanded form. |
Returns a lambda-expression of two arguments: the entire macro form and the environment in which it is expanded.
Function: PARSE-MACRO NAME LAMBDA-LIST BODY &OPTIONAL ENVIRONMENT
Parse a macro definition form (as found in MACROLET
or DEFMACRO
)
into a macro function.
This function is equivalent to the following:
(enclose (parse-macro name lambda-list body environment) environment)
NAME
-
The symbol naming the macro.
LAMBDA-LIST
-
The macro lambda-list.
BODY
-
The forms comprising the macro’s body.
ENVIRONMENT
-
The environment in which the macro definition is found. This is necessary in order for macros and symbol-macros used in
BODY
to be expanded correctly.
ℹ️
|
See AUGMENT-ENVIRONMENT and ENCLOSE for limitations of this
function.
|
Returns a function object of two arguments, suitable as a
macro-function to be passed in the :MACRO
argument of
AUGMENT-ENVIRONMENT
.
The CL-ENVIRONMENTS.CLTL2
package also provides wrapper functions,
over standard common lisp functions which take an environment
parameter, that work with both native environments and augmented
environments returned by AUGMENT-ENVIRONMENT
.
The following wrapper functions are provided, which are equivalent to
the functions in the COMMON-LISP
package with the same names but
without the leading AUGMENTED-
:
-
AUGMENTED-MACROEXPAND-1
-
AUGMENTED-MACROEXPAND
-
AUGMENTED-MACRO-FUNCTION
-
AUGMENTED-GET-SETF-EXPANSION
-
AUGMENTED-COMPILER-MACRO-FUNCTION
-
AUGMENTED-CONSTANTP
The CL-ENVIRONMENTS-CL
package shadows the following COMMON-LISP
functions with definitions which can accept either a native
environment object or an environment returned by
AUGMENT-ENVIRONMENT
:
-
MACROEXPAND-1
-
MACROEXPAND
-
MACRO-FUNCTION
-
COMPILER-MACRO-FUNCTION
-
CONSTANTP
-
GET-SETF-EXPANSION
-
TYPEP
-
SUBTYPEP
Macro IN-ENVIRONMENT (ENV-VAR &OPTIONAL (ENVIRONMENT ENV-VAR)) (&REST BINDINGS) &BODY FORMS
Evaluate FORMS
in a dynamic environment in which a native
environment object, that is equivalent to an augmented environment
object (returned by AUGMENT-ENVIRONMENT), is available.
This macro is necessary to be able to pass augmented environment objects to functions which expect a native environment object, for which there is no wrapper function.
ENV-VAR
-
Symbol naming the variable to which the native environment object is bound. This binding is made available to
FORMS
. ENVIRONMENT
-
Form which evaluates to the environment, which may be either a native or augmented environment object.
ENVIRONMENT
is evaluated in the environment of the macro form. If not provided the variable with name given byENV-VAR
is evaluated in the environment of the macro-form. BINDINGS
-
List of bindings as if by
LET
to make available toFORMS
. The difference fromLET
is that the init-forms are evaluated in the environment of the macro form but the bindings are made available in the dynamic environment in whichFORMS
are evaluated. If no init-form is given for a binding, the variable is bound to the value of the variable in the environment of the macro-form. FORMS
-
List of forms to evaluate with
ENV-VAR
bound to a native environment object equivalent of an augmented environment, and with the bindings specified byBINDINGS
. The values returned by the last form inFORMS
are returned by theIN-ENVIRONMENT
form.🔥These forms might be evaluated in a dynamic environment where they do not have access to the local variable, function and macro definitions of the environment of the macro-form, hence the need for BINDINGS
.
ℹ️
|
On implementations where AUGMENT-ENVIRONMENT is provided
natively, this macro simply expands to a LET and FORMS are
executed in the same environment as the macro form.
|
The CL-ENVIRONMENTS-CL
package already shadows all standard common
lisp special forms, which introduce an environment, with macros that
invoke the code-walker, in order for the environment information to be
extracted on implementations which do not support the CLTL2 API.
However, this may not be enough if you have a top-level third-party
macro which does not expand into one of the shadowing macros from the
CL-ENVIRONMENTS-CL
package, or if you use an implementation-specific
special form which the code-walker does not know how to walk. The
WALK-ENVIRONMENT
macro exported by both the CL-ENVIRONMENTS.CLTL2
and CL-ENVIRONMENTS-CL
package allows you to explicitly tell the
code-walker to walk a particular form.
;; WALK-ENVIRONMENT ensures that the third party DEFINE-CUSTOM-THING ;; macro is walked. (walk-environment (define-custom-thing ...))
Compiler-macro expansions and top-level macro forms which are not
contained in a WALK-ENVIRONMENT
or in a shadowing macro of a special
form are not walked. For the environment information to be extracted
in these cases there is the option of binding the code-walker to
*MACROEXPAND-HOOK*
so that it is called on each macro expansion. The
ENABLE-HOOK
function binds the code-walker to *MACROEXPAND-HOOK*
and the DISABLE-HOOK
function restores it’s previous value.
Macro: WALK-ENVIRONMENT &BODY FORMS
Ensure that forms are walked by the code-walker.
FORMS
-
The forms to be walked by the code-walker. These are evaluated in an implicit
PROGN
.
ℹ️
|
On implementations which provide the CLTL2 API natively, this
simply expands into a PROGN .
|
Function: ENABLE-HOOK &OPTIONAL PREVIOUS-HOOK
Bind the code-walker to the *MACROEXPAND-HOOK*
.
PREVIOUS-HOOK
-
The function to restore
*MACROEXPAND-HOOK*
to when callingDISABLE-HOOK
. If not provided defaults to the current value of*MACROEXPAND-HOOK*
.
💡
|
This function should be used if there are top-level macro forms which need to be walked, or you need the expansion of compiler-macros to be walked, in order for the environment information to be extracted from them. |
ℹ️
|
On implementations which provide the CLTL2 API natively this function is a no-op. |
❗
|
The functionality provided by this package has been moved to a separate project cl-form-types. |
|
This package, and the functions exported by it, are deprecated and will be removed in a future release. |
The package CL-ENVIRONMENTS.TOOLS
provides a number of functions for
obtaining information about forms occurring in a particular
environment. These functions make use of the information return by the
*-INFORMATION
functions.
Function GET-RETURN-TYPE FORM ENV
Determine the value type of the form FORM
in the environment ENV
.
The return value type can be determined if FORM
is:
-
A symbol naming a variable for which there is a
TYPE
declaration. -
A list where the
CAR
is a function for which there is anFTYPE
declaration. -
A
THE
form. -
A macro/symbol-macro which expands to one of the above.
Additionally value the types of the following special forms can also be determined:
-
PROGN
Function GET-RETURN-TYPES FORMS ENV
Determines the value type of each form in FORMS
, in the environment
ENV
.
Returns a list where each element is the value type of the
corresponding form in FORMS
.
Supports: Clisp, CCL, ECL, ABCL, CMUCL, SBCL, Allegro CL and LispWorks. Tested on: Clisp, CCL, ECL, ABCL, CMUCL and SBCL.
-
Some individual forms (such as
DEFUN
) cannot be compiled using C-c C-c in slime whileMACROEXPAND-HOOK
is set to the code walker, the entire file can still be compiled using C-c C-k. -
ABCL passes
NIL
as the environment parameter to compiler macro functions thus there is no way to obtain any information about the lexical environment in which the form appears. The environment information functions:VARIABLE-INFORMATION
,FUNCTION-INFORMATION
andDECLARATION-INFORMATION
can only return information about global bindings/declarations when called from inside a compiler macro.