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

DEFCONSTANT and EQ



    Date:  8 June 1983 0146-EDT (Wednesday)
    From: Guy.Steele@CMU-CS-A
    The initial-value form to DEFCONSTANT is conceptually evaluated at load
    time.  DEFCONSTANT is an invitation to the compiler to susbtitute the
    value for occurrences of the constant *if* the compiler is smart enough
    to do so.  DEFCONSTANT is not meant to side-effect the compiler's environment.
	    (DEFCONSTANT FOO 3)
	    (DEFCONSTANT BAR (+ FOO 6))
    entitles the compiler to use the value 9 for BAR provided that it is
    smart enough to analyze what it going on (actually notall that hard:
    the first declaration entitles the compiler to substitute 3 for FOO,
    whereupon some simple constant folding reduces (+ 3 6) to 9).

    Date: Sun, 12 Jun 1983  15:25 EDT
    From: Scott E. Fahlman <Fahlman@CMU-CS-C>

    1. DEFCONSTANT does not create a "symbol macro".  Conceptually, it
    evaluates the init form at load time and sets the global special value
    of the variable to that value.  It also causes this symbol to be
    CONSTANTP.  The semantics of DEFCONSTANT differs from DEFVAR only in
    that you must supply an init and you are declaring to the compiler that
    the value of the variable will never be changed.  The compiler can do
    whatever it wants to with that information, but it must preserve the
    variable-reference semantics.  If the user violates this declaration, it
    it "is an error" and might cause bad things to happen, but it might not
    be signalled.

    4. Given the above rules, if X is a constant defined by DEFCONSTANT, the
    compiler knows that it is safe to substitute the initial value V
    (quoted) for references to X if V is a number of any kind,
    a symbol, or any kind of immediate object whose creation
    involves no consing.  A more complex compiler might be able to
    substitute for other kinds of V if it can prove that the value is
    consumed locally in a way that does not depend on EQ-ness, and that it
    cannot escape the local environment to be EQ-tested elsewhere.

I agree with this.  An example of your last sentence would be the byte-specifier
argument to LDB.

    Date: Wednesday, 8 June 1983, 16:19-EDT
    From: Bernard S. Greenberg <BSG%SCRC-TENEX@MIT-MC>
    The loading of a DEFCONSTANT changes the symbol being defined
    in a (so far) unalterable fashion.   There ought to be an
    in-language way to revoke this effect.

This is important.  UNDEFCONSTANT is a reasonable name.

    Date: 8 June 1983 21:11 EDT
    From: Glenn S. Burke <GSB @ MIT-ML>
    The one thing which needs to be clearly specified is how the semantics
    of "added to the compilation environment" differs from what might be
    done by (eval-when (compile) ...).  If, for instance, defmacro does
    not bash the runtime environment, then the user will have to use
    eval-when if the macro needs to be usable via the interpreter during
    the compilation.  Eval-when should do exactly that:  evaluate and bash
    the runtime environment.  Always, without exception, no matter what
    "added to the compilation environment" might mean.  My own experience
    is that it is generally a loss for "added to the compilation
    environment" to bash the runtime environment.

I agree with this. (eval-when (compile ...) form) should eval form, no
ifs, ands, or buts.  Forms seen by the compiler and not inside an
eval-when-compile should not affect the run-time environment, to the
extent that is possible (it is unlikely to be possible for the package
declaration forms).  The manual should clearly document which forms
affect the environment in which the compiler (and the user's macros)
are running when seen by the compiler.

Note that, contrary to several people's mail, packages are no help
in keeping the run-time and compile-time environments straight, any
time you are compiling a program that you also run in the compiler.
Even in a system where the compiler is run in a separate Lisp, there
is an issue when compiling a system of macros, for example, since it
has to run in the compiler as well as being compiled.

Getting back to DEFCONSTANT, evaluation of its initial-value subform
should not affect the run-time environment -- the compiler should
analyze the initial value, not EVAL it.  Furthermore the value of
the symbol should not change in the compiler's environment; the
compiler should remember the constant value someplace else.  Only
when the DEFCONSTANT is actually loaded should the value of the
symbol be changed.

Later we might want to standardize some tools for getting at the
compile-time environment.  For instance, a macro running in the
compiler can use CONSTANTP to determine that a symbol has been
declared to be a DEFCONSTANT, and hence that its value won't change
no matter what code is executed between two successive references
[this is the sort of thing SETF needs to know, for example].
However the current language provides no way for that macro to
find out what the actual value of the DEFCONSTANT is.  And of
course, given the above definition the compiler may not even -know-
what the actual value of the DEFCONSTANT is going to be.  Pathologically,
	(DEFCONSTANT FUBAR (MACHINE-INSTANCE))
	(DEFCONSTANT SPAM (FUNCTION-HALTS-P 'BAZ))

    Date: Wednesday, 8 June 1983, 14:46-EDT
    From: Bernard S. Greenberg <BSG%SCRC-TENEX%MIT-MC@SU-DSN>
    The answer to "What kind of evaluator or meta-
    evaluator should be invoked on the second operand of DEFCONSTANT?" is
    "the compiler's pass-1 optimizer/reducer"!  That is not something we
    do now, but there is no good reason why not.

Actually we do do this in our "DEFSYSCONSTANT" stuff (which is
associated with the Lisp cold-load generator, declaring constants that
will be constant in the Lisp system being built.)  But we don't do it
yet in our Common Lisp DEFCONSTANT implementation.

    Date: 8 June 1983 02:47 EDT
    From: Kent M. Pitman <KMP @ MIT-MC>

    I am still bothered that on the LispM, the compiler does a
    side-effect to my compile-time environment when it sees DEFSETF,
    for example. 

Indeed, this is wrong, and some day we have to get our act together and
fix this kind of thing.  It means that DEFSETF and SETF have to have
explicit knowledge of the two separate environments, unless you don't
want merely compiling a DEFSETF (without loading it) to affect the
subsequent expansion of SETF in the same compilation.