[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
issue LOAD-TIME-EVAL, version 7
- To: cl-compiler@sail.stanford.edu
- Subject: issue LOAD-TIME-EVAL, version 7
- From: sandra%defun@cs.utah.edu (Sandra J Loosemore)
- Date: Mon, 17 Oct 88 13:02:46 MDT
Here is my new writeup on this issue. The proposal is pretty much the same
as the draft REVISED-NEW-SPECIAL-FORM I distributed earlier (with some
changes in wording), that does not tie LOAD-TIME-VALUE to #,.
-Sandra
Issue: LOAD-TIME-EVAL
References: #, (p. 356), (EVAL-WHEN (LOAD) ...) (p. 69-70)
issue SHARP-COMMA-CONFUSION
Category: ADDITION
Edit history: 06-Jun-87, Version 1 by James Kempf
17-Jul-87, Version 2 by James Kempf
12-Nov-87, Version 3 by Pitman (alternate direction)
01-Feb-88, Version 4 by Moon
(from version 2 w/ edits suggested by Masinter)
06-Jun-88, Version 5 by Pitman
(fairly major overhaul, merging versions 3 and 4)
21-Sep-88, Version 6 by Moon (stripped down)
17-Oct-88, Version 7 by Loosemore (change direction again)
Status: For internal discussion
Problem description:
Common Lisp provides reader syntax (#,) which allows the programmer
to designate that a particular expression within a program is to be
evaluated early (at load time) but to later be treated as a constant.
Unfortunately, no access to this capability is available to programs
which construct other programs without going through the reader.
Some computations can be deferred until load time by use of EVAL-WHEN,
but since EVAL-WHEN must occur only at toplevel, and since the nesting
behavior of EVAL-WHEN is quite unintuitive, EVAL-WHEN is not a general
solution to the problem of load-time computation of program constants.
Proposal (LOAD-TIME-EVAL:R**2-NEW-SPECIAL-FORM):
Add a new special form, LOAD-TIME-VALUE, which has the following
contract:
LOAD-TIME-VALUE form &optional read-only-p [Special Form]
LOAD-TIME-VALUE provides a mechanism for delaying evaluation of <form>
until the expression is in the "runtime" environment.
If a LOAD-TIME-VALUE expression is seen by COMPILE-FILE, the compiler
arranges for all semantic processing of <form> (including macro
expansion) to occur at load time in a null lexical environment. It
is guaranteed that the evaluation of <form> will take place only once
when the file is loaded, but the order of evaluation with respect to
the "evaluation" of top-level forms in the file is unspecified.
If a LOAD-TIME-VALUE expression appears within a function compiled
with COMPILE, the <form> is evaluated at compile time in a null lexical
environment. The result of this compile-time evaluation is treated as
an immediate quantity in the compiled code.
In interpreted code, (LOAD-TIME-VALUE <form>) is equivalent to (VALUES
(EVAL (QUOTE <form>))). Implementations which implicitly compile
(or partially compile) expressions passed to EVAL may evaluate the
<form> only once, at the time this compilation is performed. This is
intentionally similar to the freedom which implementations are given
for the time of expanding macros in interpreted code.
Note that, in interpreted code, there is no guarantee as to when
evaluation of <form> will take place, or the number of times the
evaluation will be performed. Since successive evaluations of the
same LOAD-TIME-VALUE expression may or may not result in an evaluation
which returns a "fresh" object, destructive side-effects to the
resulting object may or may not persist from one evaluation to the
next. It is safest to explicitly initialize the object returned by
LOAD-TIME-VALUE, if it is later modified destructively.
Implementations must guarantee that each reference to a
LOAD-TIME-VALUE expression results in at least one evaluation of its
nested <form>. It is not permissible to "collapse" either multiple
references to the same (EQ) LOAD-TIME-VALUE expression, or EQUAL
expressions. In the case of a LOAD-TIME-VALUE form appearing in a
quoted expression passed to EVAL, each call to EVAL must result in a
new evaluation of <form>. For example,
(DEFVAR X 0)
(DEFUN FOO () (EVAL '(LOAD-TIME-VALUE (INCF X))))
is guaranteed to increment X each time FOO is called, while
(DEFUN FOO () (LOAD-TIME-VALUE (INCF X)))
may cause X to be evaluated only once.
The READ-ONLY-P argument designates whether the result can be considered
read-only constant. If NIL (the default), the result must be considered
ordinary, modifiable data. If T, the result is a read-only quantity
which may, as appropriate, be copied into read-only space and/or shared
with other programs. (Because this is a special form, this argument is
-not- evaluated and only the literal symbols T and NIL are permitted.)
Rationale:
LOAD-TIME-VALUE is a special form rather than a function or macro
because it requires special handling by the compiler.
Allowing the same LOAD-TIME-VALUE to cause its nested <form> to be
evaluated more than once makes simplifies its implementation in
interpreters which do not perform a preprocessing code walk. It also
makes the rules for the time of its processing analogous to those
for macro expansion.
This proposal explicitly does -not- tie LOAD-TIME-VALUE to the #,
read macro. Doing so would be an incompatible change to the definition
of #, (which is reliably useful only -inside- quoted structure,
while LOAD-TIME-VALUE must appear -outside- quoted structure in a
for-evaluation position).
The prohibition against collapsing of shared or EQUAL LOAD-TIME-VALUE
expressions prevents problems that could result by performing destructive
side-effects on a value that is referenced in more than one place.
Current Practice:
This is an addition to the language and has not yet been implemented.
Cost to Implementors:
In compiled code, (LOAD-TIME-VALUE <form>) is equivalent to '#,<form>.
Most implementations can probably make use of the same mechanism they
use to handle #, to handle LOAD-TIME-VALUE.
Implementing LOAD-TIME-VALUE in the interpreter should be fairly
straightforward, since one simply needs to evaluate the <form> in the
null lexical environment. Implementations that use a preprocessing
code walk in the interpreter to perform macro expansion could process
LOAD-TIME-VALUE forms at that time.
Some code-walkers would have to be taught about this new
special form. Such changes would likely be trivial.
Cost to Users:
Some code-walkers would have to be taught about this new
special form. Such changes would likely be trivial.
Benefits:
Users are given a mechanism that to force evaluation to be delayed
until load time that does not rely on a feature of the reader.
Discussion:
The semantics of LOAD-TIME-VALUE would be simplified considerably if
the READ-ONLY-P argument were removed and destructive operations on
the result of evaluating <form> prohibited. However, some people feel
that the ability to destructively modify the value is an important
feature to include.
"Collapsing" of equivalent LOAD-TIME-VALUE expressions could be
allowed for read-only situations, but it seems like it would be more
confusing to make it legal in some situations and not in others.
A number of other alternatives have been considered on this issue,
including:
- A proposal for a new special form that would force evaluation of
the <form> to happen only once. This was rejected because of
implementation difficulties.
- A proposal to add a function making the "magic cookie" used by #,
available to user code. The current proposal does not prevent such
a function from being added, but this approach appeared to have
less support than making the hook available as a new special form.
- A proposal to remove #, entirely (issue SHARP-COMMA-CONFUSION).
- A suggestion to change the behavior of (EVAL-WHEN (LOAD) ...). Note
that the current proposal forces -all- processing of the <form> to
be delayed until load-time, while the body of an (EVAL-WHEN (LOAD) ...)
is compiled normally.
-------