The functions eval
and compile
are
required to ensure that literal objects referenced within the resulting
interpreted or compiled code objects are the same as the
corresponding objects in the source code.
compile-file
, on the other hand,
must produce a compiled file that, when loaded with
load
, constructs the objects defined by the
source code and produces references to them.
In the case of compile-file
, objects
constructed by load
of the compiled file cannot be spoken
of as being the same as the objects constructed at
compile time, because the compiled file may be loaded into a different
Lisp image than the one in which it was compiled. This section
defines the concept of similarity which relates
objects in the evaluation environment to the
corresponding objects in the run-time environment.
The constraints on literal objects described in this section
apply only to compile-file
;
eval
and compile
do not copy or coalesce constants.
The fact that the file compiler represents literal objects externally in a compiled file and must later reconstruct suitable equivalents of those objects when that file is loaded imposes a need for constraints on the nature of the objects that can be used as literal objects in code to be processed by the file compiler.
An object that can be used as a literal object in code to be processed by the file compiler is called an externalizable object.
We define that two objects are similar if they satisfy a two-place conceptual equivalence predicate (defined below), which is independent of the Lisp image so that the two objects in different Lisp images can be understood to be equivalent under this predicate. Further, by inspecting the definition of this conceptual predicate, the programmer can anticipate what aspects of an object are reliably preserved by file compilation.
The file compiler must cooperate with the loader in order to assure that in each case where an externalizable object is processed as a literal object, the loader will construct a similar object.
The set of objects that are externalizable objects are those for which the new conceptual term “similar” is defined, such that when a compiled file is loaded, an object can be constructed which can be shown to be similar to the original object which existed at the time the file compiler was operating.
Of the types over which similarity is defined, some are treated as aggregate objects. For these types, similarity is defined recursively. We say that an object of these types has certain “basic qualities” and to satisfy the similarity relationship, the values of the corresponding qualities of the two objects must also be similar.
Two objects S (in source code) and C (in compiled code) are defined to be similar if and only if they are both of one of the types listed here (or defined by the implementation) and they both satisfy all additional requirements of similarity indicated for that type.
number
Two numbers S and C are similar if they are of the same type
and represent the same mathematical value.
character
Two simple characters S and C are similar if they have similar code attributes.
Implementations providing additional, implementation-defined
attributes must define whether and how non-simple characters
can be regarded as similar.
symbol
Two apparently uninterned symbols S and C are similar if their names are similar.
Two interned symbols S and C are similar if their names are similar, and if either S is accessible in the current package at compile time and C is accessible in the current package at load time, or C is accessible in the package that is similar to the home package of S.
(Note that similarity of
symbols is dependent
on neither the current readtable nor how the function read
would
parse the characters in the name of the symbol.)
package
Two packages S and C are similar if their names are similar.
Note that although a package object is an externalizable object,
the programmer is responsible for ensuring that the corresponding package is
already in existence when code referencing it as a literal object
is loaded. The loader finds the corresponding package object
as if by calling find-package
with that name as an argument.
An error is signaled by the loader if no package exists at load time.
random-state
Two random states S and C are similar if S
would always produce the same sequence of pseudo-random numbers
as a copy5 of C
when given as the random-state argument to the function random
,
assuming equivalent limit arguments in each case.
(Note that since C has been processed by the file compiler,
it cannot be used directly as an argument to random
because random
would perform a side effect.)
cons
Two conses, S and C, are similar if
the car2 of S is similar to the car2 of C,
and the cdr2 of S is similar to the cdr2 of C.
array
Two one-dimensional arrays, S and C, are similar if the length of S is similar to the length of C, the actual array element type of S is similar to the actual array element type of C, and each active element of S is similar to the corresponding element of C.
Two arrays of rank other than one, S and C, are similar if the rank of S is similar to the rank of C, each dimension1 of S is similar to the corresponding dimension1 of C, the actual array element type of S is similar to the actual array element type of C, and each element of S is similar to the corresponding element of C.
In addition,
if S is a simple array, then C must also be a simple array.
If S is a displaced array,
has a fill pointer,
or is actually adjustable,
C is permitted to lack any or all of these qualities.
hash-table
Two hash tables S and C are similar if they meet the following three requirements:
eql
hash tables).
If there is more than one possible one-to-one correspondence between
the keys of S and C, the consequences are unspecified.
A conforming program cannot use a table such as S as an
externalizable constant.
pathname
Two pathnames S and C are similar if all corresponding
pathname components are similar.
function
Functions are not externalizable objects.
structure-object
and standard-object
A general-purpose concept of similarity does not exist for structures
and standard objects.
However, a conforming program is permitted to define a make-load-form
method for any class K defined by that program that is
a subclass of either structure-object
or standard-object
.
The effect of such a method is to define that an object S of type K
in source code is similar to an object C of type K
in compiled code if C was constructed from code produced by
calling make-load-form
on S.
Some objects, such as streams, readtables
, and methods
are not externalizable objects under the definition of similarity given above.
That is, such objects may not portably appear as literal objects
in code to be processed by the file compiler.
An implementation is permitted to extend the rules of similarity, so that other kinds of objects are externalizable objects for that implementation.
If for some kind of object, similarity is neither defined by this specification nor by the implementation, then the file compiler must signal an error upon encountering such an object as a literal constant.
If two literal objects appearing in the source code for a single file processed with the file compiler are the identical, the corresponding objects in the compiled code must also be the identical. With the exception of symbols and packages, any two literal objects in code being processed by the file compiler may be coalesced if and only if they are similar; if they are either both symbols or both packages, they may only be coalesced if and only if they are identical.
Objects containing circular references can
be externalizable objects.
The file compiler is required to preserve eql
ness of
substructures within a file.
Preserving eql
ness means that subobjects that are
the same
in the source code must
be
the same
in the corresponding compiled code.
In addition, the following are constraints on the handling of literal objects by the file compiler:
find-package
with the package name as an argument.
An error of type package-error
is signaled if no
package of that name exists at load time.
random
because random
modifies this data structure.
structure-object
and standard-object
may appear in compiled constants if there is an
appropriate make-load-form
method defined for that
type.
The file compiler calls make-load-form
on any object
that is referenced as a literal object if the object is a
generalized instance of standard-object
,
structure-object
, condition
, or any of a
(possibly empty) implementation-dependent set of other classes.
The file compiler only calls make-load-form
once for
any given object within a single file.
compile-file
must be the same as the current package
when the code corresponding to that top level form in the
compiled file is executed by load
. In particular:
in-package
form, then the current package
at the time load
is called must be a package with the
same name as the package that was the current package
at the time compile-file
was called.
If any of these conditions do not hold, the package in which the loader looks for the affected symbols is unspecified. Implementations are permitted to signal an error or to define this behavior.