[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
issue LOAD-TIME-EVAL
- To: Sandra J Loosemore <sandra%defun@cs.utah.edu>
- Subject: issue LOAD-TIME-EVAL
- From: David A. Moon <Moon@STONY-BROOK.SCRC.Symbolics.COM>
- Date: Tue, 16 Aug 88 18:02 EDT
- Cc: cl-compiler@SAIL.STANFORD.EDU, kmp@STONY-BROOK.SCRC.Symbolics.COM
- In-reply-to: <8808112052.AA03499@defun.utah.edu>
Date: Thu, 11 Aug 88 14:52:56 MDT
From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
Here are some of my thoughts on cleaning up the existing proposal for
LOAD-TIME-EVAL:NEW-SPECIAL-FORM. I haven't yet heard anybody
objecting to discarding the QUOTED-MAGIC-TOKEN proposal on the same
issue -- speak now or forever hold your peace!
Consider this a speech.
LOAD-TIME-CONSTANT form &optional read-only-p [Special Form]
All processing of the FORM is deferred until the expression is
in the "runtime" environment. Once that environment is available,
FORM is evaluated in the null lexical environment and the result
is both returned and saved for immediate access by the program
on subsequent evaluations.
In the interpreter, the FORM may be evaluated during pre-processing
(if any) or dynamically when the LOAD-TIME-CONSTANT is first seen
(in a non-pre-processing implementation). If the same LOAD-TIME-CONSTANT
expression is later seen again by the interpreter, the previously
obtained result is immediately retrieved and returned as the result
of evaluating the object; no re-evaluation occurs.
I don't know what "all processing" means. For example, does this forbid
the compiler from performing optimizations that it might perform on other
expressions in a file being compiled? Or does it just mean evaluation?
There is some possible confusion over what "the same LOAD-TIME-CONSTANT
expression" means; in particular, is it the entire LOAD-TIME-CONSTANT
form or the evaluable form inside of it that is compared? What predicate
is used to compare them -- EQ or EQUAL? And, is it the *reference* to
the LOAD-TIME-CONSTANT form that is checked, or the form itself --
something which makes a big difference given that there may be multiple
references to the same code fragment? In other words, is it a legitimate
implementation technique for the interpreter to destructively bash the
list (LOAD-TIME-EVAL <foo>) into (QUOTE <what-foo-evaluates-to>)?
All of these issues would be avoided by using something more compatible
with the way the #, reader syntax works. I don't recall a quoted-magic-token
proposal (perhaps I have not read it yet), but a technique where the
primitive offered is a way to create a data object that can be used
only inside a quoted constant would avoid all these problems, as long
as we know what "the same" means for quoted constants, and I think we do.
The primitive should be a function, not a special form, and should take
two arguments, a form and an optional macroexpansion environment. The
form is either evaluated immediately in the null lexical environment
(when not compiling to a file) and its value returned, or encapsulated
in a magic compiler/loader recognizable object (when compiling to a file)
and evaluated in the null lexical environment later when the file is loaded.
The purpose of the macroexpansion environment argument is to distinguish
whether the quoted constant being constructed is destined for the current
environment or for a compiler output file [I believe this is a pending
issue, unless it's been resolved recently.]
I don't believe in the read-only-p argument, since I believe all constants
are inherently read-only, and that anyone using constants to simulate
variables (as some Interlisp programs do) should be using variables instead.
(defmacro load-time-constant (form &environment env)
`(quote ,(sharp-comma form env)))
If the LOAD-TIME-CONSTANT expression is seen by the file compiler
(eg, COMPILE-FILE), the compiler arranges for all semantic processing
of FORM (including macro expansion) to occur at load time in a null
lexical environment (independent of whether any value has been cached
for interpreter use). At runtime, the result of that evaluation will
be treated as an immediate quantity; no re-evaluation occurs.
Doing macro expansion in a null lexical environment makes this behave
more like (EVAL-WHEN (COMPILE) ...) than (EVAL-WHEN (LOAD) ...).
If a LOAD-TIME-CONSTANT expression is seen by the runtime compiler
(eg, COMPILE), the compiler checks for a cached value which may have
been produced by the interpreter. If one is found, it is used. If no
such value is found, the runtime compiler will evaluate the FORM in
a null lexical environment and use that value. The value used will be
treated as an immediate quantity in the code which is produced; no
re-evaluation occurs.
Is the compiler supposed to cache the value of FORM for later use by
the interpreter? Again, this is a concern if there are multiple
references to the same expression.
The above couple paragraphs seem to be examples of the confusion rampant
in Common Lisp, between two meanings of "the compiler." One is "a program
that makes programs run faster by converting them to machine instructions",
the other is "a program that makes files load faster by converting them to
a binary format." While these are often used together, only the second
form of compiler is relevant to #,. I think understanding this distinction
ought to clear things up.