From: Kelly Murray
Subject: eval-when-compile in #'compile
Date: 
Message-ID: <35D89138.43C11187@IntelliMarket.Com>
Common Lisp says an (eval-when (compile) ...) is only evaled
at compile time by #'compile-file.  Why not by #'compile ?
The function #'compile is the only non-file-based way to 
invoke the compiler, and it will fail to work properly when the code
being compiled has eval-when-compiles, and suddenly code that
worked using files, breaks badly when files aren't used. 

-kelly murray

From: Sunil Mishra
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <efyhfzbnmng.fsf@jiffy.cc.gatech.edu>
Kelly Murray <···@IntelliMarket.Com> writes:

> Common Lisp says an (eval-when (compile) ...) is only evaled
> at compile time by #'compile-file.  Why not by #'compile ?
> The function #'compile is the only non-file-based way to 
> invoke the compiler, and it will fail to work properly when the code
> being compiled has eval-when-compiles, and suddenly code that
> worked using files, breaks badly when files aren't used. 
> 
> -kelly murray

I think the hyperspec cleans up this issue a little. load, compile and eval
are now deprecated for eval-when. The equivalents are now load-toplevel,
compile-toplevel and execute. I suppose it ought to be less ambiguous how
eval-when functions.

Sunil
From: Barry Margolin
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <7G0C1.8$Gz4.329993@burlma1-snr1.gtei.net>
In article <·················@IntelliMarket.Com>,
Kelly Murray  <···@IntelliMarket.Com> wrote:
>Common Lisp says an (eval-when (compile) ...) is only evaled
>at compile time by #'compile-file.  Why not by #'compile ?
>The function #'compile is the only non-file-based way to 
>invoke the compiler, and it will fail to work properly when the code
>being compiled has eval-when-compiles, and suddenly code that
>worked using files, breaks badly when files aren't used. 

The :COMPILE-TOPLEVEL keyword in EVAL-WHEN, as its new name implies, only
has an effect when it appears at top-level.  The COMPILE function can only
compile function definitions, so it never sees top-level forms.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Kent M Pitman
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <sfwg1evugfz.fsf@world.std.com>
Kelly Murray <···@IntelliMarket.Com> writes:

> Common Lisp says an (eval-when (compile) ...) is only evaled
> at compile time by #'compile-file.  Why not by #'compile ?
> The function #'compile is the only non-file-based way to 
> invoke the compiler, and it will fail to work properly when the code
> being compiled has eval-when-compiles, and suddenly code that
> worked using files, breaks badly when files aren't used. 
> 
> -kelly murray

Don't do that then.

The reason we renamed COMPILE to :COMPILE-TOPLEVEL and LOAD to
:LOAD-TOPLEVEL wasn't just to break all your programs.  It was to
clarify that the function of COMPILE was nothing to do with the
function COMPILE.  Rather, it is about the concept of compiling in a
separate environment from execution.  As such, "half" the work may
want to be done at compile time while the other "half" may want to be
done at load time.  The EVAL time was renamed to :EXECUTE to emphasize
that it means "any time you're in the runtime environment, whether or
not it's just EVAL."  If you have "must do" work in an EVAL-WHEN with
keyword compile, then you need to rethink whether you also need a
:EXECUTE.  The language is not broken; you're just missing another
case.  The conceptual proof that this is right is that the same code
run interpreted has to work, too, and can only work if there is a
:EXECUTE.
From: Kelly Murray
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <35D9D6AE.2D8E8786@IntelliMarket.Com>
The eval-when names are insignificant to this problem. 
Change my gripe to be (eval-when (:compile-toplevel) ..) is broken then.
So please tell me how to fix my problem.
The solution as I see it is to reimplement my own #'compile 
that processes eval-when's.  The solution suggested by Franz
is to have my macro have side effects by EVALing the eval-when forms
inside the macro. This is very bad style of course,
and effectively just a "cheap and dirty"
implementation of redefining #'compile to process eval-when's

(defmacro defsomething (name &rest body)
 `(progn
   (eval-when (compile load eval)
    (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
    )
   (defun somethingize (x)
      (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
   ))
    
So please tell me how NOT to do this then, what "case" must I cover?

-kelly

>Kent M Pitman wrote:
> 
> Kelly Murray <···@IntelliMarket.Com> writes:
> 
> > Common Lisp says an (eval-when (compile) ...) is only evaled
> > at compile time by #'compile-file.  Why not by #'compile ?
> > The function #'compile is the only non-file-based way to
> > invoke the compiler, and it will fail to work properly when the code
> > being compiled has eval-when-compiles, and suddenly code that
> > worked using files, breaks badly when files aren't used.
> >
> > -kelly murray
> 
> Don't do that then.
> 
> The reason we renamed COMPILE to :COMPILE-TOPLEVEL and LOAD to
> :LOAD-TOPLEVEL wasn't just to break all your programs.  It was to
> clarify that the function of COMPILE was nothing to do with the
> function COMPILE.  Rather, it is about the concept of compiling in a
> separate environment from execution.  As such, "half" the work may
> want to be done at compile time while the other "half" may want to be
> done at load time.  The EVAL time was renamed to :EXECUTE to emphasize
> that it means "any time you're in the runtime environment, whether or
> not it's just EVAL."  If you have "must do" work in an EVAL-WHEN with
> keyword compile, then you need to rethink whether you also need a
> :EXECUTE.  The language is not broken; you're just missing another
> case.  The conceptual proof that this is right is that the same code
> run interpreted has to work, too, and can only work if there is a
> :EXECUTE.
From: Kent M Pitman
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <sfwaf52x984.fsf@world.std.com>
Kelly Murray <···@IntelliMarket.Com> writes:

> The eval-when names are insignificant to this problem. 
> Change my gripe to be (eval-when (:compile-toplevel) ..) is broken then.
> So please tell me how to fix my problem.
> The solution as I see it is to reimplement my own #'compile 
> that processes eval-when's.  The solution suggested by Franz
> is to have my macro have side effects by EVALing the eval-when forms
> inside the macro. This is very bad style of course,
> and effectively just a "cheap and dirty"
> implementation of redefining #'compile to process eval-when's
> 
> (defmacro defsomething (name &rest body)
>  `(progn
>    (eval-when (compile load eval)
>     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
>     )
>    (defun somethingize (x)
>       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
>    ))
>     
> So please tell me how NOT to do this then, what "case" must I cover?

First, COMPILE doesn't take a form as an argument, it takes a function
name.  So the DEFMACRO here must be getting evaluated before you use COMPILE
or you'd never be able to call, I assume, (compile 'somethingize).
The EVAL keyword SHOULD cause the LISP:DEFTYPE to get evaluated.

If instead you're doing something like
 (compile nil '(lambda () (defsomething ...)))
then you must funcall the result in order for the EVAL part to get run.

I really hate to suggest that a Harlequin competitor has a bug, but if
Franz is not executing the EVAL-WHEN form with the EVAL keyword, it
sure sounds like a bug.  In fairness, little bugs like this could
happen in any implementation.  The pre-ANSI semantics left more leeway
than the ANSI semantics do, and maybe they just haven't upgraded that
yet. The whole Lisp industry is working on tightening up holes like
this, but it takes time. On the other hand, you didn't provide a
fully worked example, including the COMPILE call, so I can't be sure.

My point was that it's not just true that the deftype must be done at
compile time; what's really true is that it must be done at execution
time prior to semantically processing the DEFUN, regardless of whether
compilation is ongoing.  The mention of COMPILE is a red-herring here.
This action has to be done even if you're only using an interpreter,
just in case the interpreter looks to see if the first arg to THE is a
valid type, which some interpreters might.

I still don't think this is a language definition problem; I think
you're just getting faked out by an implementation behavior that
you assume is correct but may not be.  
From: Kelly Murray
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <35DA1991.6FFEDDC8@IntelliMarket.Com>
> > (defmacro defsomething (name &rest body)
> >  `(progn
> >    (eval-when (compile load eval)
> >     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
> >     )
> >    (defun somethingize (x)
> >       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
> >    ))
> >
> If instead you're doing something like
>  (compile nil '(lambda () (defsomething ...)))
> then you must funcall the result in order for the EVAL part to get run.

This is what I'm doing, and yes, I will funcall the result to 
get the EVAL part (and effectively "define the something"),
but the problem is the COMPILE part.  The compile stage will fail,
because the deftype is not processed at compile time when
the lambda function passed to #'compile is compiled.

Just for more information, effectively I am "loading" a source code
module by compiling all the forms in it.
If one of those forms is (defsomething ...) it will fail.

(defun load-module (forms)
 (loop for form in forms
       for fun = (compile nil `(lambda () ,form)) ;; compile it
     do
    (when fun (funcall fun)) ;; eval/load it
    ))

but all is hunky-dory if I use #'compile-file, and cons up 
a dummy file to compile instead, e.g.

(defun load-module-using-ansi-common-lisp (forms)
 (loop for form in forms 
       for file = (cons-up-a-source-file-to-compile form)
       for fasl = (compile-file file)
     do
    (load fasl)  
    ;; oops, forgot to delete the source and fasl files,
    ;; because GC won't do it for me...
    ))
  

> 
> I really hate to suggest that a Harlequin competitor has a bug, but if
> Franz is not executing the EVAL-WHEN form with the EVAL keyword, it
> sure sounds like a bug.  In fairness, little bugs like this could
> happen in any implementation.  The pre-ANSI semantics left more leeway
> than the ANSI semantics do, and maybe they just haven't upgraded that
> yet. The whole Lisp industry is working on tightening up holes like
> this, but it takes time. On the other hand, you didn't provide a
> fully worked example, including the COMPILE call, so I can't be sure.
> 
> My point was that it's not just true that the deftype must be done at
> compile time; what's really true is that it must be done at execution
> time prior to semantically processing the DEFUN, regardless of whether
> compilation is ongoing.  The mention of COMPILE is a red-herring here.
> This action has to be done even if you're only using an interpreter,
> just in case the interpreter looks to see if the first arg to THE is a
> valid type, which some interpreters might.
> 
> I still don't think this is a language definition problem; I think
> you're just getting faked out by an implementation behavior that
> you assume is correct but may not be.
From: Howard R. Stearns
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <35DB1678.9E65E137@elwood.com>
Kelly Murray wrote:
> 
> > > (defmacro defsomething (name &rest body)
> > >  `(progn
> > >    (eval-when (compile load eval)
> > >     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
> > >     )
> > >    (defun somethingize (x)
> > >       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
> > >    ))
> > >
> > If instead you're doing something like
> >  (compile nil '(lambda () (defsomething ...)))
> > then you must funcall the result in order for the EVAL part to get run.
> 
> This is what I'm doing, and yes, I will funcall the result to
> get the EVAL part (and effectively "define the something"),
> but the problem is the COMPILE part.  The compile stage will fail,
> because the deftype is not processed at compile time when
> the lambda function passed to #'compile is compiled.
> 
> Just for more information, effectively I am "loading" a source code
> module by compiling all the forms in it.
> If one of those forms is (defsomething ...) it will fail.
> 
> (defun load-module (forms)
>  (loop for form in forms
>        for fun = (compile nil `(lambda () ,form)) ;; compile it
>      do
>     (when fun (funcall fun)) ;; eval/load it
>     ))
> 
> but all is hunky-dory if I use #'compile-file, and cons up
> a dummy file to compile instead, e.g.
> 
> (defun load-module-using-ansi-common-lisp (forms)
>  (loop for form in forms
>        for file = (cons-up-a-source-file-to-compile form)
>        for fasl = (compile-file file)
>      do
>     (load fasl)
>     ;; oops, forgot to delete the source and fasl files,
>     ;; because GC won't do it for me...

(Supercedes any previous message that sneaked out through my flaky
news connection...)

At Elwood, we are working on a new compiler for Eclipse.  Part of the
design is that each form is (recursively) processed using a generic
function with four required arguments: 
 - the form being processed
 - a "processor" representing the top level compilation environment
 - the lexical environment
 - a continuation (details are not important for this discussion)

Thus, one could write something like:

(defun load-module (forms &optional (compiler (make-file-compiler))
  (loop for form in forms 
        for result = (process '(lambda () ,form) compiler nil nil)
        do (funcall result)))

The point is that the top-level compilation environment can be resused
through different calls to PROCESS.  Furthermore, this object could
represent either the "run-time" compiler or a "file-compiler"

There are other issues involved.  For example, WITH-COMPILATION-UNIT
can be used to share top-level processing environments from one
invocation to the next.  The precise type of the object returned by
PROCESS 
will actually depend on the continuation, etc.

The protocol is more general, allowing user-defined processors, and
methods specialized on them.  (It's really a MOP for
compilers/code-walkers.)  In fact, the interpreter and compiler both
use the same system -- they're just different "top level processing
environments" and there are a handful of specialized methods for each.
You could use this to write your own processor which did the compiling
and loading in a single step.  Furthermore, you could use something
other than lists to represent "forms" to be processed, and define
appropriate specialized methods.

We were planning to use this internally, and perhaps, maybe, to
someday document the protocol so that users could have access.

I mention all this to see if there is much of a current demand.  If we
get 47 letters saying, "If Eclipse did this, I would immediate buy and
use it", then I'll make sure this gets finished up and documented as
soon as possible.  On the other hand, if we just get a bunch of mail
saying "this is a [bad|good] idea because...", I'll still find the
feedback usefull.

For what it's worth, Eclipse does let you forward-reference
types. It's just that more efficient code is generated if the type is
defined before code that references it is compiled.  The type system
is actually implemented as a TYPE-MOP (somewhat like Dylan), which
could also be documented and exposed, but that's another story.
(Frankly, I don't think we know enough about TYPE-MOPs do expose it
yet.)

(More info on Eclipse in general at http://www.elwood.com/eclipse-info)
From: Kent M Pitman
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <sfw1zqd1zl7.fsf@world.std.com>
Kelly Murray <···@IntelliMarket.Com> writes:

> 
> > > (defmacro defsomething (name &rest body)
> > >  `(progn
> > >    (eval-when (compile load eval)
> > >     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
> > >     )
> > >    (defun somethingize (x)
> > >       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
> > >    ))
> > >
> > If instead you're doing something like
> >  (compile nil '(lambda () (defsomething ...)))
> > then you must funcall the result in order for the EVAL part to get run.
> 
> This is what I'm doing, and yes, I will funcall the result to 
> get the EVAL part (and effectively "define the something"),
> but the problem is the COMPILE part.  The compile stage will fail,
> because the deftype is not processed at compile time when
> the lambda function passed to #'compile is compiled.
 
That's not EVAL-WHEN's problem.  You can regard it as a bug in THE
that it doesn't support forward references.  I'm not sure if it's an
implementation bug or a language bug, since I don't recall if the
language permits/requires that to fail (and I'm too lazy to look).  It
seems to me intuitively that the worst that should happen is that THE
ignores the type and the semantic processor fails to give you the
value of having done the type declaration if nothing yet is known
about the type.  But I can imagine people wanting it to do more. 

> Just for more information, effectively I am "loading" a source code
> module by compiling all the forms in it.
> If one of those forms is (defsomething ...) it will fail.
> 
> (defun load-module (forms)
>  (loop for form in forms
>        for fun = (compile nil `(lambda () ,form)) ;; compile it
>      do
>     (when fun (funcall fun)) ;; eval/load it
>     ))
> 

I don't know what that (when fun ...) thing is since COMPILE is
going to always return a function in the case you're using, which
will always be true, so
 (defun load-module (forms) 
   (dolist (form forms) (funcall (compile nil `(lambda () ,form)))))
is going to be the same as what you wrote.

> but all is hunky-dory if I use #'compile-file, and cons up 
> a dummy file to compile instead, e.g.
> 
> (defun load-module-using-ansi-common-lisp (forms)
>  (loop for form in forms 
>        for file = (cons-up-a-source-file-to-compile form)
>        for fasl = (compile-file file)
>      do
>     (load fasl)  
>     ;; oops, forgot to delete the source and fasl files,
>     ;; because GC won't do it for me...
>     ))

The bug isn't really the handling of COMPILE or EVAL-WHEN with
COMPILE here.  The bug is that the semantics of COMPILE-FILE and
COMPILE differ in other ways than you're acknowledging.  For
example, if you do:

 (DEFVAR *FOO* 1)
 (DEFMACRO FOO () *FOO*)
 (DEFUN BAR () (FOO))
 (INCF *FOO*)
 (DEFUN BAZ () (FOO))

you will get very different behavior than if you put the
same set of forms in a file and compile it.  The problem is that
you're creating a situation in which you rely on the interleaving
of execution with compilation and you're assuming that's the same
as doing compilation for the whole file followed by execution of
the whole file.  It's not.

It's also not a safe transformation to assume that a file full of
forms has the same semantics as the same forms wrapped in a PROGN.
Consider:

 
 (PROGN (SETQ X 3)
        (IN-PACKAGE "KEYWORD")
        (CL:PRINT (CL:LIST X))
        (CL:IN-PACKAGE "CL-USER")
        T)

vs the same without the parens.  OR

 (PROGN (SETQ *READ-BASE* 8.) (PRINT (+ 10 10)) (SETQ *READ-BASE* 10.))

So when you say it works with COMPILE-FILE and not with COMPILE, you
aren't just saying "it works with text files and not with forms"
you're again saying "it works when I interleave evaluation with
execution" and you wonder why it doesn't work when you don't.

What you really want is to get a hook when semantic processing is done
and force an operation that might not ordinarily happen.  
  (LAMBDA () ...)
as the Scheme people would tell you [not that they're the in the same
language family :-] is a way of delaying evaluation.  It would be
semantically entirely inappropriate to force evaluation of something
within that, since  you don't know that it will ever be called.  For
example, I might have:
 (LAMBDA (X) (IF X (DEFTYPE FOO () 'INTEGER) (DEFTYPE FOO () 'FLOAT)))
and you definitely don't want to assume one of these deftypes has
compile-time effect.  Further, it doesn't help to wrap it with 
EVAL-WHEN since
 (LAMBDA (X)
  (IF X
    (EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO () 'INTEGER))
    (EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO () 'FLOAT))))
can't be executed because you just don't know the value of X until 
runtime.  That's exactly why the COMPILE and LOAD keywords MUST NOT
execute if not at top-level.  And it doesn't help to say
 (LAMBDA ()
   (EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'INTEGER)))
because the situation might still be
 (FUNCALL (IF X
	      (LAMBDA ()    
		(EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'INTEGER)))
	      (LAMBDA ()    
		(EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'FLOAT)))))
So just because there is no lexical state (bound variables, go tags,
etc. doesn't mean the mere fact of the LAMBDA isn't holding off
evaluation).  So if you write:

 (LAMBDA ()
   (EVAL-WHEN (CIMPILE LOAD EVAL) (DEFTYPE FOO 'INTEGER))
   (THE FOO Y))

you're asking really a lot of the implementation to distinguish:
 (FUNCALL (IF X
	      (LAMBDA ()    
		(EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'INTEGER))
                (THE FOO Y))
	      (LAMBDA ()    
		(EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'FLOAT))
	        (THE FOO Y))))
from
 (PROGN (FUNCALL (IF X
	         (LAMBDA ()    
		   (EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'INTEGER))
                    )
   	        (LAMBDA ()    
		   (EVAL-WHEN (COMPILE LOAD EVAL) (DEFTYPE FOO 'FLOAT))
	            )))
    (THE FOO Y))

I'm doing a lot of cutting and pasting here with a fairly arbitrary
example to illustrate a rather obscure point of philosophy, but I hope
the abstract point mostly makes sense to you even though I'm working
with a few highly concrete cases that may not illustrate the full
range of potential pitfalls.

Just to be fair, I'll point out that most implementations will let you
do what you want in a horrible awful way that you shouldn't really
do if you think about the accidents of environmental overlap that are
going on and if you realize that it's mostly just a weakness in most 
implementations that they allow this (I think the spec says to try
not to let this happen, but doesn't forbid you from permitting it because
it's too hard):

The trick?  Use MACROLET instead.  Consider:

 (defmacro kem-eval-when ((&rest times) form)
   (let ((kludge (gensym "I-DESERVE-TO-LOSE-FOR-DOING-THIS")))
     `(or
        ,(if (member 'compile times)
            `(progn (macrolet ((,kludge () ,form)) ,kludge) ;NOT ',form !!
		    t))
        ,(if (or (member 'load times) (member 'eval times))
	     `(progn (eval ',form) t))
	nil)))

I was too embarrassed to test this.  It's too gross.  But you can see
what it's doing--MACROLET's job is to run at semantic analysis time.
But then you want to avoid double-evaluation in interpreted code, so
the OR is kind of kludging around that.  And the return values have to
be discarded since there's c"ompetition" between the compile time
result and the run time result and we have to paper over that.  And,
perhaps most importantly, the form is being evaluated in two utterly
different environments--one that sees any lexical bindings and go tags
and other stuff like that, and one that doesn't.  So the code
surrounding it and the form itself have to be written carefully to not
ask too much of the form.  

Still, it might win for your purposes.  For varying values of win.
(I'm reminded of a remark I saw on a bathroom wall when I first got to
MIT.  It said Limit(sqrt(10))->3 .... for very small values of 10.)
From: David D. Smith
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <dds-1908980056080001@x064.bit-net.com>
In article <·················@IntelliMarket.Com>, Kelly Murray
<···@IntelliMarket.Com> wrote:

> > > (defmacro defsomething (name &rest body)
> > >  `(progn
> > >    (eval-when (compile load eval)
> > >     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
> > >     )
> > >    (defun somethingize (x)
> > >       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
> > >    ))
> > >
> > If instead you're doing something like
> >  (compile nil '(lambda () (defsomething ...)))
> > then you must funcall the result in order for the EVAL part to get run.
> 
> This is what I'm doing, and yes, I will funcall the result to 
> get the EVAL part (and effectively "define the something"),
> but the problem is the COMPILE part.  The compile stage will fail,
> because the deftype is not processed at compile time when
> the lambda function passed to #'compile is compiled.


You can't get there from here.

Cf. CLtL2 5.3.3 Control of Time of Evaluation
Rebared section starting with "X3J13 voted in March 1989 <73> to
completely redesign the EVAL-WHEN construct..."

"For an EVAL-WHEN form that is not a top-level form in the file compiler
(that is, either in the interpreter, in COMPILE, or in the file compiler
but not at top level), if the :EXECUTE situation is specified, its body is
treated as an implicit PROGN. Otherwise the body is ignored and the
EVAL-WHEN form has the value NIL."

IOW the EVAL-WHEN containing your DEFTYPE is treated as a PROGN by
COMPILE, and never the twain shall meet.

Since all this stuff is generated by a macro why not just substitute
FIXNUM everwhere you use ZAPPER.  Or...


(defmacro defsomething (name &rest body)
  (lisp:deftype zapper () 'fixnum)
  `(progn
    (eval-when (:compile-toplevel :load-toplevel)
     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
     )
    (defun somethingize (x)
       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
    ))

Or...


(lisp:deftype zapper () 'fixnum)

(defmacro defsomething (name &rest body)
  `(progn
    #+ignore ;If ZAPPER not needed at runtime
    (eval-when (:compile-toplevel :load-toplevel)
     (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
     )
    (defun somethingize (x)
       (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
    ))
From: Barry Margolin
Subject: Re: eval-when-compile in #'compile
Date: 
Message-ID: <I3mC1.23$Gz4.942329@burlma1-snr1.gtei.net>
In article <·················@IntelliMarket.Com>,
Kelly Murray  <···@IntelliMarket.Com> wrote:
>The eval-when names are insignificant to this problem. 
>Change my gripe to be (eval-when (:compile-toplevel) ..) is broken then.
>So please tell me how to fix my problem.
>The solution as I see it is to reimplement my own #'compile 
>that processes eval-when's.  The solution suggested by Franz
>is to have my macro have side effects by EVALing the eval-when forms
>inside the macro. This is very bad style of course,
>and effectively just a "cheap and dirty"
>implementation of redefining #'compile to process eval-when's
>
>(defmacro defsomething (name &rest body)
> `(progn
>   (eval-when (compile load eval)
>    (lisp:deftype zapper () 'fixnum)  ;; MUST BE DONE AT COMPILE TIME!!
>    )
>   (defun somethingize (x)
>      (the zapper x))  ;; BROKEN BECAUSE NO DEFTYPE AT COMPILE TIME!!
>   ))
>    
>So please tell me how NOT to do this then, what "case" must I cover?

If you're using the COMPILE function, then the compile-time environment
inherits from the run-time environment.  So all you have to do is evaluate
the DEFTYPE before calling COMPILE, you don't need an explicit EVAL-WHEN,
e.g.

(defun compile-it ()
  (eval '(lisp:deftype zapper () 'fixnum))
  (compile 'somethingize))

I'm not sure if this really addresses your concern.  Could you show what
you were trying to write, and where you wanted to put the EVAL-WHEN?  It
looks like what you're trying to do is outside the function, but COMPILE
can only be given functions to compile.  Compiling a function doesn't have
any side effects other than on the function name's binding.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.