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

nesting of EVAL-WHENs

I've been trying to write up some formal proposals to firm up what we
now seem to think is the "right" way to handle defining macros and
eval-when, and I've run into a problem with the semantics of nested

 From our Palo Alto meeting, there seemed to be some consensus that the
following kind of code should "work":

(eval-when (eval compile load)
    (let ((x  (some-hairy-computation)))
        (defmacro foo (y)
            `(+ ,x ,y))))

Namely, the macro function FOO should be closed over X, and since the value
of X is available at compile time everything should be hunky-dory.

According to our model of how the compiler treats top-level forms,
the defmacro itself expands into another eval-when, something like

(eval-when (eval compile load)
    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load)
            (setf (macro-function 'foo)
                #'(lambda (form env)
                      (let ((y  (second form)))
                          `(+ ,x ,y))))

So, here's the problem.  As I understand our latest spec on how
EVAL-WHEN works, the compiler will first evaluate the entire LET form
that binds X in the null lexical environment, and FOO will get the
"right" macro definition as a function closed over X.  Then, the
compiler will do the processing for the LOAD part of the EVAL-WHEN.  In
doing so, it will hit that nested EVAL-WHEN, see that COMPILE is
specified among the situations, and promptly redefine the macro
definition of FOO as a function in the null lexical environment which
is not closed over X.  Which isn't what we wanted to happen.

I thought of maybe saying that LOAD or EVAL processing of the body of
the EVAL-WHEN disables COMPILE processing of nested EVAL-WHENs in
the body.  This would be incompatible with the current behavior as
specified in CLtL, however, and I'm not sure that it would be generally
the right thing to do in other situations.  Alternatively, we could keep
the current restriction on macro functions always being defined in the
null lexical environment, but that would be difficult to explain using
our model of how defining macros work.

Anybody else have thoughts on this?