[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

issue SYNTACTIC-ENVIRONMENT-ACCESS, version 4



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.
-------