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

Issue EVAL-WHEN-NON-TOP-LEVEL, v2



re: If you'll please look at issue DEFINING-MACROS-NON-TOP-LEVEL, it is
    not a requirement that defining macros expand into EVAL-WHENs.

Yes, I'm very well aware of that (and I don't prefer it!), which is
why I reminded you that I prefer the version of defining macros that
expands into simpler constructs including EVAL-WHENs.

Well, in the rebuttals and counter rebuttals, we've lost track of
what was at issue -- namely whether or not you could implement
defining macros by expanding them into EVAL-WHEN's.  I claim you 
can, even when EVAL-WHEN is defined as a macro that macrolet's
EVAL-WHEN so that inner (lexical) nested instances don't cause
the evalueate twice (or, evaluate 2â??<n-1> times) problem.  Your
rebuttal:

    From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
    Date: Sun, 8 Jan 89 11:17:03 MST
    Subject: Re: Issue EVAL-WHEN-NON-TOP-LEVEL, v2

    This implies that you couldn't implement DEFMACRO by expanding 
    it into an EVAL-WHEN, because the required magic actions would 
    be suppressed.

is apparently predicated on the assumption that the envelopping
macrolet takes the defining form from a toplevel status to a 
non-toplevel status?  If so, then I have two questions:
  -- couldn't we permit MACROLET to "pass back" toplevel, just
     as John Rose suggested
  -- why does it matter anyway?  It could conceivably matter if
     the defining form expanded into something whose outter-most
     wrapper was an EVAL-WHEN -- but you would do this only if you
     wanted evaluation in the compile-time environment rather than
     "special magic"; and my counter-rebuttal showed that you do
     indeed get evaluation at that point, regardless of whether
     it is considered to be at toplevel.

On the other hand, I would like to continue to raise my objection to 
"special magic" that isn't regular evaluation.  This tactic at best
leads to very confusing semantics, and can hardly be portable.  For 
example, suppose one implementation really does evaluate the 
IN-PACKAGE's and DEFMACRO's it finds at toplevel, while another
doesn't really evaluate them, but merely affects some internal 
compiler state.  Then various macroexpander functions will not
see a consistent state between one implementation and another.

I think this leads to a satisfactory example of something that will
"break" if you retain the notion of "toplevel magic".  Bacher could
come up with a related example of something that would "break" if you 
take away toplevelness from the bodies of eval-whens -- it wouldn't be 
a portable breakage since it would rely on an implementation-specific
"magic" processor.  Of course, there would be no problem if we insisted 
that EVAL-WHEN "pass back" toplevelness.  [I can give an example of the
non-portable "breakage" in Lucid Common Lisp, based on some particular
"magic" that occurs with toplevel DEFUN's that doesn't occur with
inner DEFUN's -- needless to say, I consider this a bug, albeit very 
minor, in Lucid Common Lisp.]


Trying to insulate the compiler's environment is a weak straw man
here.  Simply shielding toplevel DEFMACROS and DEFSTRUCTS isn't
satisfactory in general, because it is wrong to think that only
two environments are at stake (the "compilation host" one and that 
of the compilation target).  The most realistic example I can think
of right now is one that we called "the XYZ machine problem" in our
1986 Lisp Conference paper on Lucid's retargetable compiler.

Consider compiling a program which is part of a retargetable compiler;
this program has code that is sensitive to DEFMACRO and DEFCONSTANT
definitions that will vary between one intended target and another.
During any one given compilation, this retargetable program will
itself be concerned with two environments: that on which it is expected
to be running, and that for which it is intended to be producing code.
More specifically, let's say that we are building a cross- compiler
which is intended to be _running_ on a 80386 machine, where it will
be _producing_ code to be run on a PRIME machine.  Of course, we are 
compililng the cross-compiler from a Sun3 workstation.  Thus at any 
one given instant in time, during the compilation of the cross-compiler,
there are _three_ different environments that must be separated.

The solution was that we had to introduce parallel new definers and 
new accessors to reach these relativized environments.  We didn't add 
every conceivable definer, but enough to make the cross-compiler itself 
be compilable from anywhere (maybe, just def-compiler-macro and 
def-target-constant?).  That is also why the Schemer's (and the 
Lisp/370er's) glory in their Lisp1 world: by having only one thing to 
define -- a variable's value -- there is only one aspect of an environment 
to be relativized (the variables values) rather than the spectrum of
MACRO-FUNCTION, SYMBOL-FUNCTION, SYMBOL-VALUE, Defstruct-Definitions,
CONSTANTP, etc.

As it happens, I think I was the one who, way back when, put the
"special magic" into the toplevel processor of MacLisp's compiler;
probably before any other implementation did so (this question could 
not arise in "residential environments" like Interlisp).  It may have
been OK for the early 1970's; it is too limiting and wrong now.


-- JonL --