From: Peter Seibel
Subject: Help with Sec. 3.2.3.1.1
Date: 
Message-ID: <m33cpma5ng.fsf@localhost.localdomain>
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

From: Barry Margolin
Subject: Re: Help with Sec. 3.2.3.1.1
Date: 
Message-ID: <IJdF9.70$sA6.1408@paloalto-snr1.gtei.net>
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.
From: Peter Seibel
Subject: Re: Help with Sec. 3.2.3.1.1
Date: 
Message-ID: <m3vg2i8mvv.fsf@localhost.localdomain>
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
From: Kent M Pitman
Subject: Re: Help with Sec. 3.2.3.1.1
Date: 
Message-ID: <sfwhee1aarr.fsf@shell01.TheWorld.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.