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

time of evaluation

    Date: Wed, 15 Jan 86 09:11 EST
    From: Bernard S. Greenberg <BSG@SCRC-STONY-BROOK.ARPA>

    This is completely unclear.  Consider an incompatible change to a defstruct
    used by the compiler.

(Are you aware that defstruct is implicitly "(compile load eval)" in our
implementation, and always has been?)

The real issue here is what it means to "compile from a file".  It's a
tricky issue when the Lisp environment that's running the compiler is
not a special Lisp created only for that compilation and then discarded
(the way we used to do it in Maclisp), but is an ongoing environment.

When the compiler sees a "defmacro" early in a file, it ideally should
not actually alter the Lisp environment at all, but it should let forms
in the file use that macro.  It needs to maintain a "subjunctive Lisp
environment", in which the contract of the compiler, given a Lisp
fucntion to compile, is to produce code that will do the same thing that
the interpreted code would do if that interpreted code were run in the
"subjunctive environment", which means "if all the previous stuff file,
but not the subsequent stuff, had been evaluated".

The Symbolics implementation really does maintain a "subjunctive
environment" for macros.  But it doesn't do a perfect job.  Consider a
file with the following forms:

(defun util (x) (list x x))

(defmacro mac (y) (util y))

(defun test (z) (mac z))

Now, if you call compile-file on this file, your Lisp environment should
not end up having "util" defined when you are done.  Yet, "util" needs
to be in the "subjunctive environment", so that when the compiler tries
to compile "mac", it will be able to.  Our implementation of
compile-file signals "The function UTIL is not defined."  I'd be interested
to know if any implementation handles this correctly.

The current practice is that the programmer has to get around this by
inserting an eval-when around the definition of util (or put it into a
"defs" file that gets loaded before compilation, which is really the
same thing).  The problem is that it conflicts with/overrides the
definition of "util" in the running environment.

This is essentially the same problem as the one you are pointing out, in
the "defstruct that's part of the compiler" example, except that
breaking the compiler is obviously a more serious thing that will lead
to immediate worse problems.  Richard is right about how users don't
hack the compiler much, but it's still true that using (eval-when
(compile ...) ...)  breaks the principle that compile-file should leaves
the state of the Lisp environment unchanged, and user programs can
definitely suffer from this problem: you compile a new version, and the
suddently the old version doesn't work any more, perhaps because you
modified some function like util.