[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
issue SYNTACTIC-ENVIRONMENT-ACCESS, version 4
- To: cl-compiler@sail.stanford.edu
- Subject: issue SYNTACTIC-ENVIRONMENT-ACCESS, version 4
- From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
- Date: Sun, 12 Mar 89 10:59:59 MST
I've done a rather substantial re-organization on this issue. There
are now three proposals, SMALL, MEDIUM, and LARGE. I did this because
I personally didn't feel comfortable with standardizing more than the
material in proposal SMALL at this point, and maybe others will also
be more inclined to vote for a minimal proposal than a larger one that
includes material of less obvious usefulness.
I've made the change to AUGMENT-ENVIRONMENT (adding a :DECLARE argument)
that I suggested in a previous message.
I've also removed the RECORD-ENVIRONMENT-CLEANUP function. I couldn't
think of any good examples of how or why one would want to use this,
that couldn't also be achieved by putting an explicit UNWIND-PROTECT
in the body of the WITH-REMOTE-ENVIRONMENT.
Forum: Compiler
Issue: SYNTACTIC-ENVIRONMENT-ACCESS
References: CLtL Chapter 8: Macros,
Issue MACRO-FUNCTION-ENVIRONMENT,
Issue GET-SETF-METHOD-ENVIRONMENT,
Issue COMPILE-FILE-ENVIRONMENT
Related Issues: Issue FUNCTION-NAME,
Issue PROCLAIM-LEXICAL
Issue MACRO-ENVIRONMENT-EXTENT
Category: ADDITION
Edit history: Version 1, 2-Oct-88, Eric Benson
Version 2, 17-Feb-89, Kim A. Barrett
Version 3, 9-Mar-89, Kim A. Barrett (respond to comments)
Version 4, 12-Mar-89, Sandra Loosemore (more revisions)
Status: **DRAFT**
Problem description:
When macro forms are expanded, the expansion function is called with
two arguments: the form to be expanded, and the environment in which
the form was found. The environment argument is of limited utility.
The only use sanctioned currently is as an argument to MACROEXPAND or
MACROEXPAND-1 or passed directly as an argument to another macro
expansion function. Recent cleanup issues propose to allow it as an
argument to MACRO-FUNCTION and to GET-SETF-METHOD.
It is very difficult to write a code walker that can correctly handle
local macro and function definitions, due to insufficient access to
the information contained in environments and the inability to
augment environments with local definitions.
Some people believe that the CLOS meta-object protocol will require the
ability to distinguish between remote environments used for compiling
to a file, from local environments used for processing by EVAL or
COMPILE. (However, there is no requirement in chapters 1 & 2 of the
CLOS spec that things be done this way.)
There are three proposals; SMALL, MEDIUM, and LARGE.
Proposal (SYNTACTIC-ENVIRONMENT-ACCESS:SMALL):
The following functions provide information about syntactic
environment objects. In all of these functions the argument named ENV
is an environment of the sort received by the &ENVIRONMENT argument to
a macro or as the environment argument for EVALHOOK. Optional "env"
arguments default to NIL, which respresents the local null lexical
environment (containing only global definitions and proclamations
that are present in the runtime 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.
VARIABLE-KIND variable &optional env [Function]
VARIABLE is a symbol. This function returns one of the following
symbols, depending on the type of definition or binding which is
apparent in ENV.
NIL There is no apparent definition or binding for variable.
:SPECIAL VARIABLE refers to a special variable, either declared
or proclaimed.
:LEXICAL VARIABLE refers to a lexical variable.
:SYMBOL-MACRO VARIABLE refers to a SYMBOL-MACROLET binding.
:CONSTANT VARIABLE refers to a named constant, defined by
DEFCONSTANT.
[Note: If issue PROCLAIM-LEXICAL passes, then the :LEXICAL result
will also refer to variables proclaimed lexical.]
Example:
(DEFMACRO KIND-OF-VARIABLE (VAR &ENVIRONMENT ENV)
`',(VARIABLE-KIND VAR ENV))
(DEFVAR A)
(DEFUN TEST ()
(LET (B)
(LET (C)
(DECLARE (SPECIAL C))
(SYMBOL-MACROLET ((D ANYTHING))
(LIST (KIND-OF-VARIABLE A)
(KIND-OF-VARIABLE B)
(KIND-OF-VARIABLE C)
(KIND-OF-VARIABLE D)
(KIND-OF-VARIABLE E))))))
(TEST) -> (:SPECIAL :LEXICAL :SPECIAL :SYMBOL-MACRO NIL)
FUNCTION-KIND function &optional env [Function]
FUNCTION is a function name. This function returns two values,
depending on the type of function definition or function binding
which is apparent for FUNCTION in ENV.
NIL There is no apparent definition for FUNCTION.
:FUNCTION FUNCTION refers to a function.
:MACRO FUNCTION refers to a macro.
:SPECIAL-FORM FUNCTION refers to a special form.
The second value specifies whether the definition is local or
global. If local, the second value is true, and it is false when
the definition is global.
Some function names may 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.
[Note: The use of "function name" rather than "symbol" as the
description of the function argument is intended to be compatible
with the various proposals to extend the syntax of function
specifiers. If no such change actually occurs then this would only
refer to symbols.]
Example:
(DEFMACRO KIND-OF-FUNCTION (FUNCTION-NAME &ENVIRONMENT ENV)
`',(FUNCTION-KIND FUNCTION-NAME ENV))
(DEFUN A ())
(DEFMACRO B ())
(DEFUN TEST ()
(FLET ((C ()))
(MACROLET ((D ()))
(MULTIPLE-VALUE-CALL #'LIST
(KIND-OF-FUNCTION A)
(KIND-OF-FUNCTION B)
(KIND-OF-FUNCTION QUOTE)
(KIND-OF-FUNCTION C)
(KIND-OF-FUNCTION D)
(KIND-OF-FUNCTION E)))))
(TEST) -> (:FUNCTION NIL
:MACRO NIL
:SPECIAL-FORM NIL
:FUNCTION T
:MACRO T
NIL NIL)
VARIABLE-TYPE variable &optional env [Function]
VARIABLE is a symbol. This function returns the type specifier
associated with the variable named by the symbol in the environment.
If no explicit association exists, either by PROCLAIM or DECLARE,
then the result is the type specifier T.
The result of this function may not include all the apparent TYPE
declarations for VARIABLE. In particular, an implementation is free
to ignore TYPE declarations, only returning TYPE information which
was added to ENV by a call to AUGMENT-ENVIRONMENT.
Example:
This example assumes that the implementation records type
information in the environment, rather than ignoring it.
(DEFMACRO VARTYPE (VAR &ENVIRONMENT ENV)
`',(VARIABLE-TYPE VAR ENV))
(DEFVAR A 1)
(PROCLAIM '(FIXNUM A))
(DEFUN TEST ()
(LET ((B (AREF "X" 0))
(C 3))
(DECLARE (STRING-CHAR B))
(LIST (VARTYPE A) (VARTYPE B) (VARTYPE C))))
(TEST) -> (FIXNUM STRING-CHAR NIL)
FUNCTION-FTYPE function &optional env [Function]
FUNCTION is a function name. This function returns the functional
type specifier associated with the function in the environment, or
the symbol FUNCTION if there is no functional type declaration or
proclamation associated with the function.
The result of this function may not include all the apparent FTYPE
declarations for FUNCTION. In particular, an implementation is free
to ignore FTYPE declarations, only returning FTYPE information which
was added to ENV by a call to AUGMENT-ENVIRONMENT.
Example:
This example assumes that the implementation records ftype
information in the environment, rather than ignoring it.
(DEFMACRO FUNTYPE (FUN &ENVIRONMENT ENV)
`',(FUNCTION-FTYPE FUN ENV))
(DEFUN A-FUNCTION (X)
(+ X 3))
(PROCLAIM '(FTYPE (FUNCTION (FIXNUM) FIXNUM) A-FUNCTION))
(DEFUN TEST ()
(FLET ((ANOTHER-FUNCTION (X)
(+ X 2)))
(DECLARE (FTYPE (FUNCTION (INTEGER) INTEGER) ANOTHER-FUNCTION))
(LIST (FUNTYPE A-FUNCTION) (FUNTYPE ANOTHER-FUNCTION))))
(TEST) -> ((FUNCTION (FIXNUM) FIXNUM) (FUNCTION (INTEGER) INTEGER))
AUGMENT-ENVIRONMENT env &KEY variable
symbol-macro
function
macro
declare [Function]
This function returns a copy of ENV, augmented with the information
provided by the keyword arguments. The arguments are supplied as
follows:
:VARIABLE A list of symbols which shall 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 list.
:SYMBOL-MACRO A list of symbol macro definitions, 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.
:FUNCTION A list of function names which shall be visible as local
function bindings in the new environment.
:MACRO A list of local macro definitions, in the same format
as the CADR of a MACROLET special form. 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 A list of decl-specs. The new environment will
contain information about SPECIAL, TYPE, and FTYPE
declarations appearing within the list.
An error is signalled if any of the symbols naming macros in the
:SYMBOL-MACRO alist are also included in the :VARIABLE list.
An error is signalled if any of the names specified as keys in the
:MACRO alist are also included in the :FUNCTION list. The consequences
of destructively modifying the list structure of any of the arguments
to this function are undefined.
The extent of the returned environment is the same as the extent of
the argument.
While an environment argument from EVALHOOK may be used as the
environment argument for this function, the reverse is not true. If
an attempt is made to use the result of AUGMENT-ENVIRONMENT as
the environment argument for EVALHOOK, the consequences are undefined.
The environment returned by AUGMENT-ENVIRONMENT may only be used for
syntactic analysis, ie. the functions specified by this proposal and
functions such as MACROEXPAND.
[If PROCLAIM-LEXICAL is adopted, LEXICAL declarations would also
be recognized.]
Rationale:
This proposal defines a minimal set of accessors and a constructor
for environments.
The symbol-macro and macrolet definitions and declarations passed
to AUGMENT-ENVIRONMENT are in the same form as those which would
normally be encountered by a code-walker. This makes it easier to
use. In particular, there is no need for users to write their own
code to destructure macro arguments.
Making TYPE and FTYPE information optional continues to allow
implementations the freedom to simply ignore all such declarations.
Proposal (SYNTACTIC-ENVIRONMENT-ACCESS:MEDIUM):
This is the same as proposal SMALL, but also includes:
There are two kinds of environments, local and remote. Local
environments are created by EVAL and COMPILE, and are used in
situations where the information in the environment pertains
to the immediate running Lisp environment. Remote environments
are used by processors such as COMPILE-FILE to model what the
Lisp environment will look like when the code being processed
is actually loaded.
If AUGMENT-ENVIRONMENT receives a remote environment as an argument,
then the new environment returned by this function will also be
remote, and the two will refer to the same model of the remote
environment.
ENVIRONMENT-REMOTE-P env [Function]
Returns true if ENV is a remote environment, false otherwise.
WITH-REMOTE-ENVIRONMENT var &body body [Macro]
Evaluates the BODY forms with VAR bound to a newly created remote
environment. The extent of the environment is the dynamic extent of
the WITH-REMOTE-ENVIRONMENT form.
This is the only specified mechanism by which a new remote
environment may be created.
Rationale:
The notion of local and remote environments may be useful for
developing the CLOS meta-object protocol. At some future time,
we may wish to tighten the specification of how compile-time
definitions of defining macros such as DEFMACRO or DEFCLASS are
achieved, by saying that the compile-time definitions must be made
only in the remote environment.
Proposal (SYNTACTIC-ENVIRONMENT-ACCESS:LARGE):
This is the same as proposal MEDIUM, but also includes:
ENVIRONMENT-PROPERTY env name property &optional default
This function and its SETF method allow the association of arbitrary
'global' properties with names within an environment. An
environment can be thought of as having a local property list
associated with any name, and this function provides access to that
property list.
A remote environment may be thought of as an extension of the local
environment. Thus, when this function is applied to a remote
environment and the property is not found, the global local environment
is then searched.
The association between names and property lists uses EQUAL to match
names. The search of the property list uses EQ to match properties.
If the property is not found, DEFAULT is returned.
Using SETF of ENVIRONMENT-PROPERTY affects all environments which
refer to the same environment model. In particular, if ENV is a
local environment then all local environments are affected, while if
ENV is a remote environment, then all environments refering to the
same remote environment model as the argument are affected.
[Note: The local property list of a name is not necessarily the
symbol-plist of the name, though that is a possible implementation
for names which are symbols.
Note: The use of EQUAL as the matching function for names is to
allow for proposed extensions to function names. If no such
extension occurs, then EQ could be used instead.]
Rationale:
This would provide a mechanism for making and accessing global
definitions in the remote environment.
Cost to Implementors:
Most implementations already record some of this information in some
form. Providing these functions should not be too difficult, but it
is a more than trivial amount of work.
Cost to Users:
This change is upward compatible with user code.
Current practice:
No implementation provides all of this interface currently. Portable
Common Loops defines a subset of this functionality for its code
walker and implements it on a number of diffent versions of Common
Lisp. IIM uses the functionality provided by ENVIRONMENT-REMOTE-P
and ENVIRONMENT-PROPERTY (under other names) to implement the
association between names and remote metaobjects (macro and type
definitions, CLOS remote metaobjects, &etc).
Discussion:
The first version of this proposal expressly did not deal with the
objects which are used as environments by EVALHOOK. This version is
extended to support them in the belief that such environments share a
lot of functionality with the syntactic environments needed by a
compiler. While the two types of environments may have very
different implementations, there are many operations which are
reasonable to perform on either type, including all of the accessor
functions described by this proposal.
AUGMENT-ENVIRONMENT currently requires signaling an error when
symbol-macro names match variable names in the same call. This could
be reduced to "should signal". By requiring the error signaling, this
proposal is compatable with Proposal SYMBOL-MACROLET-DECLARE:ALLOW,
which says
"... signals an error if a SPECIAL declaration names one of the symbols
being defined as a symbol-macrolet."
Maintaining compatability with the SYMBOL-MACROLET-DECLARE proposal
allows fairly trivial implementations of the SYMBOL-MACROLET
special-form in terms of the AUGMENT-ENVIRONMENT function.
An possible alternative syntax for WITH-REMOTE-ENVIRONMENT might be
WITH-REMOTE-ENVIRONMENT (var &key) &body body
Can anyone suggest candidates for keyword options? We could do this
even if we can't think of any immediately, leaving room for
implementation-specific extensions. One candidate option that some
implementations might want would be to specify a target machine for
the compilation.
Kim Barrett originally suggested that WITH-COMPILATION-UNIT should
provide the mechanism for creating new remote environments. However,
it has been suggested that WITH-COMPILATION-UNIT is intended to serve
a somewhat different purpose.
Sandra Loosemore says:
I support proposal SMALL but would vote against both of the larger
proposals. It's true that they provide functionality which *might* be
useful to implement CLOS, but there is nothing now in the standard
that *requires* this functionality to be added. In fact, the version
of issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS that was accepted at
the January meeting explicitly leaves unspecified the mechanism by
which defining macros make definitions available to the compiler. We
have very little practical experience with using environment objects
for this purpose and I think it would be premature to try to
standardize it at this point. In particular, since the meta-object
protocol is still undergoing what appear to be substantial changes,
let's wait until it settles down and then see what kind of compiler
hooks it needs, instead of possibly standardizing the wrong thing.
-------