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

issue EVAL-WHEN-NON-TOP-LEVEL, version 2

Here's a first cut at the new proposal.  Comments, flames, etc. are welcome.

References:	CLtL p. 69-70
Edit History:   6-May-88, V1 by Sandra Loosemore
		16 Dec 1988, V2 by Sandra Loosemore (alternate direction)

Problem Description:

The current description of how the compiler should handle EVAL-WHEN
only makes sense when it appears as a top-level form in the file being
compiled.  Is it legitimate for EVAL-WHEN to appear in non-top-level
locations?  What does it mean in such places?


Clarify that EVAL-WHEN may appear both at top-level and at
non-top-level.  In non-top-level locations, however, the COMPILE
situation is effectively ignored.

More specifically, when an EVAL-WHEN form is processed by the
interpreter (that is, by the function EVAL), the presence of the EVAL
situation indicates that the body of the EVAL-WHEN should be evaluated
as an implicit PROGN.  Otherwise, EVAL-WHEN returns NIL without
evaluating the body.

When an EVAL-WHEN form is processed by the compiler:

    (1) If the situation COMPILE is specified:

        - If the EVAL-WHEN form appears at top level, then each of the
          forms within the body of the EVAL-WHEN are evaluated by the
	  compiler in the null lexical environment using the function

	- Otherwise, no compile-time evaluation takes place.  An
          implementation is permitted to signal a warning to indicate
          that the compile-time evaluation is being ignored.

    (2) If the situation LOAD is specified, then the compiler treats
        the body of the EVAL-WHEN form as if it were an implicit PROGN.
        If the situation LOAD is not specified, then the compiler should
        treat the EVAL-WHEN form as if it were a constant value of NIL.


Restricting compile-time evaluation to top-level locations prevents
complications resulting from performing the evaluation in the wrong
lexical environment.

The behavior specified for top-level EVAL-WHENs in this proposal
differs slightly from that described in CLtL.  In the case where both
COMPILE and LOAD are specified, CLtL indicates that the compile-time
evaluation should be interleaved with normal compiler processing of
each of the forms in the body, while this proposal specifies that the
evaluation of all of the body forms should take place before any of
the normal compiler processing (leading to possible multiple
evaluations in the case of nested EVAL-WHENs).  However, it is
unlikely that this would cause serious problems for any user programs.
The nesting behavior of EVAL-WHEN as described in CLtL has been
criticized as overly complicated and hard to understand, while this
proposal is much less complicated.

Allowing implementations to signal a warning when ignoring a
non-top-level EVAL-WHEN allows users to be informed that something
unusual is going on.

Current Practice:

IIM Common Lisp implements this proposal.  Kim Barrett contributed the
following code that illustrates their implementation:

    (defmacro eval-when (situations &body body &environment env)
      (if (not (compiler-environment-p env))
          (when (member 'eval situations) `(progn ,@body))
	    (when (member 'compile situations)
	      (if (compiler-at-top-level-p env)
	          (mapc #'eval body)
	          (warn "Top-level form encountered at non-top-level.")))
	    (when (member 'load situations) `(progn ,@body)))))

Cost to implementors:

Probably fairly minor in most implementations.  

Cost to users:

Except for the change relating to possible multiple evaluation of
nested EVAL-WHENs, this proposal is a compatible extension.


The behavior of EVAL-WHEN is easier to understand.  Making EVAL-WHEN
meaningful at non-top-level locations makes it more generally useful,
for example in the expansion of defining macros.


Proposal DEFINING-MACROS-NON-TOP-LEVEL:ALLOW provides a definition for
the term "top-level".