Looking at section 3.2.3.1.1 of the CLHS (Processing of Defining
Macros) I see this:
In particular, the information stored by the defining macros at
compile time might or might not be available to the interpreter
(either during or after compilation), or during subsequent calls to
the compiler.
Is the following a correct paraphrase of the above, using the
definitions of 'compilation environment' and 'evaluation environment'
from Section 3.2.1 (Compiler Terminology)?
In particular, the information stored by the defining macros at
compile time may be stored in the compilation environment which
might or might not be the same as the environment available to the
interpreter, namely the evaluation environment
Section 3.2.3.1.1 continues:
For example, the following code is nonportable because it assumes
that the compiler stores the macro definition of foo where it is
available to the interpreter:
(defmacro foo (x) `(car ,x))
(eval-when (:execute :compile-toplevel :load-toplevel)
(print (foo '(a b c))))
A portable way to do the same thing would be to include the macro
definition inside the eval-when form, as in:
(eval-when (:execute :compile-toplevel :load-toplevel)
(defmacro foo (x) `(car ,x))
(print (foo '(a b c))))
Does the portable version work reliably because moving the DEFMACRO
form inside the EVAL-WHEN causes it to store all it's definitions in
the evaluation environment rather than the compilation environment? Or
because it somehow causes the PRINT form be evaluated in the
compilation environment. Or some other reason?
-Peter
--
Peter Seibel
·····@javamonkey.com
In article <··············@localhost.localdomain>,
Peter Seibel <·····@javamonkey.com> wrote:
>Looking at section 3.2.3.1.1 of the CLHS (Processing of Defining
>Macros) I see this:
>
> In particular, the information stored by the defining macros at
> compile time might or might not be available to the interpreter
> (either during or after compilation), or during subsequent calls to
> the compiler.
>
>Is the following a correct paraphrase of the above, using the
>definitions of 'compilation environment' and 'evaluation environment'
>from Section 3.2.1 (Compiler Terminology)?
>
> In particular, the information stored by the defining macros at
> compile time may be stored in the compilation environment which
> might or might not be the same as the environment available to the
> interpreter, namely the evaluation environment
Correct.
>Section 3.2.3.1.1 continues:
>
> For example, the following code is nonportable because it assumes
> that the compiler stores the macro definition of foo where it is
> available to the interpreter:
>
> (defmacro foo (x) `(car ,x))
> (eval-when (:execute :compile-toplevel :load-toplevel)
> (print (foo '(a b c))))
>
> A portable way to do the same thing would be to include the macro
> definition inside the eval-when form, as in:
>
> (eval-when (:execute :compile-toplevel :load-toplevel)
> (defmacro foo (x) `(car ,x))
> (print (foo '(a b c))))
>
>Does the portable version work reliably because moving the DEFMACRO
>form inside the EVAL-WHEN causes it to store all it's definitions in
>the evaluation environment rather than the compilation environment? Or
>because it somehow causes the PRINT form be evaluated in the
>compilation environment. Or some other reason?
It works because the macro is defined in *both* the evaluation environment
(because of :EXECUTE) and the compilation environment (because of
:COMPILE-TOPLEVEL). The PRINT form will be evaluated in both environments
as well, and this ensures that the macro is available in either case.
--
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
Barry Margolin <······@genuity.net> writes:
> In article <··············@localhost.localdomain>,
> Peter Seibel <·····@javamonkey.com> wrote:
> >Looking at section 3.2.3.1.1 of the CLHS (Processing of Defining
> >Macros) I see this:
> >
> > In particular, the information stored by the defining macros at
> > compile time might or might not be available to the interpreter
> > (either during or after compilation), or during subsequent calls
> > to the compiler.
> >
> >Is the following a correct paraphrase of the above, using the
> >definitions of 'compilation environment' and 'evaluation
> >environment' from Section 3.2.1 (Compiler Terminology)?
> >
> > In particular, the information stored by the defining macros at
> > compile time may be stored in the compilation environment which
> > might or might not be the same as the environment available to
> > the interpreter, namely the evaluation environment
>
> Correct.
Phew! ;-)
> >Section 3.2.3.1.1 continues:
> >
> > For example, the following code is nonportable because it assumes
> > that the compiler stores the macro definition of foo where it is
> > available to the interpreter:
> >
> > (defmacro foo (x) `(car ,x))
> > (eval-when (:execute :compile-toplevel :load-toplevel)
> > (print (foo '(a b c))))
> >
> > A portable way to do the same thing would be to include the macro
> > definition inside the eval-when form, as in:
> >
> > (eval-when (:execute :compile-toplevel :load-toplevel)
> > (defmacro foo (x) `(car ,x))
> > (print (foo '(a b c))))
> >
> >Does the portable version work reliably because moving the DEFMACRO
> >form inside the EVAL-WHEN causes it to store all it's definitions
> >in the evaluation environment rather than the compilation
> >environment? Or because it somehow causes the PRINT form be
> >evaluated in the compilation environment. Or some other reason?
>
> It works because the macro is defined in *both* the evaluation
> environment (because of :EXECUTE) and the compilation environment
> (because of :COMPILE-TOPLEVEL). The PRINT form will be evaluated in
> both environments as well, and this ensures that the macro is
> available in either case.
Er, now I'm confused again. How does the :EXECUTE affect anything?
According to the table in 3.2.3.1, the handling of EVAL-WHEN when
:COMPILE-TOPLEVEL and :LOAD-TOPLEVEL are both specified (as they are
in this example) is completely determined, without regard to either
the presence of :EXECUTE or the current mode:
CT LT E Mode Action New Mode
----------
Yes Yes --- --- Process compile-time-too
Leaving that aside, let me see if I can corretly explain the rest of
what happens. The consequence of moving the DEFMACRO inside the
EVAL-WHEN is that the DEFMACRO form will be evaluated in
compile-time-too mode instead of not-compile-time mode. DEFMACRO is
itself a macro so we macroexpand it and evaluate its expansion as a
top-level form, still in compile-time-too mode. Presumably somewhere
in the expansion of the DEFMACRO is some code that does a (setf
(macro-function 'foo) ...) so that when we load the compiled code, the
macro will be defined in the run-time environment. By virtue of that
form being processed in compile-time-too mode, we will run that code
in the evaluation environment which is the same environment our PRINT
expression will be evaluated in thanks to the EVAL-WHEN. The changes
to the compilation environment (assuming it's a different environment)
happen by virtue of the same implementation-dependent magic they
always did.
Looking at the macroexpansion of (defmacro foo (x) `(car ,x)) in ACL I
see that there are some magical looking chunks of code (calling
functions like EXCL::COMPILER-PUTPROP) that are wrapped in EVAL-WHEN's
with only the :COMPILE-TOPLEVEL situation. Those chunks of code,
according to the 3.2.3.1 table and the definition of the "Evaluate"
action are going to get evaluated in the evaluation environment
regardless of whether the DEFMACRO form is inside or outside *our*
EVAL-WHEN; I assume those magic functions have their own ways of
putting stuff in the compilation environment so the fact that they are
evaluated in the evaluation environment is not particularly relevant.
-Peter
--
Peter Seibel
·····@javamonkey.com
Peter Seibel <·····@javamonkey.com> writes:
> > > A portable way to do the same thing would be to include the macro
> > > definition inside the eval-when form, as in:
> > >
> > > (eval-when (:execute :compile-toplevel :load-toplevel)
> > > (defmacro foo (x) `(car ,x))
> > > (print (foo '(a b c))))
> > >
> > >Does the portable version work reliably because moving the DEFMACRO
> > >form inside the EVAL-WHEN causes it to store all it's definitions
> > >in the evaluation environment rather than the compilation
> > >environment? Or because it somehow causes the PRINT form be
> > >evaluated in the compilation environment. Or some other reason?
> >
> > It works because the macro is defined in *both* the evaluation
> > environment (because of :EXECUTE) and the compilation environment
> > (because of :COMPILE-TOPLEVEL). The PRINT form will be evaluated in
> > both environments as well, and this ensures that the macro is
> > available in either case.
>
> Er, now I'm confused again. How does the :EXECUTE affect anything?
:EXECUTE is used if you run this code interpreted or if you run the
code not at toplevel.