Next: , Previous: File Compilation, Up: Compilation


3.2.4 Literal Objects in Compiled Files

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.

3.2.4.1 Externalizable Objects

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.

3.2.4.2 Similarity of Literal Objects

3.2.4.2.1 Similarity of Aggregate Objects

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.

3.2.4.2.2 Definition of Similarity

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:

  1. They both have the same test (e.g., they are both eql hash tables).
  2. There is a unique one-to-one correspondence between the keys of the two hash tables, such that the corresponding keys are similar.
  3. For all keys, the values associated with two corresponding keys are similar.

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.

3.2.4.3 Extensions to Similarity Rules

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.

3.2.4.4 Additional Constraints on Externalizable Objects

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 eqlness of substructures within a file. Preserving eqlness 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:

array: If an array in the source code is a simple array, then the corresponding array in the compiled code will also be a simple array. If an array in the source code is displaced, has a fill pointer, or is actually adjustable, the corresponding array in the compiled code might lack any or all of these qualities. If an array in the source code has a fill pointer, then the corresponding array in the compiled code might be only the size implied by the fill pointer.
packages: The loader is required to find the corresponding package object as if by calling 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-state: A constant random state object cannot be used as the state argument to the function random because random modifies this data structure.
structure, standard-object: Objects of type 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.

symbol: In order to guarantee that compiled files can be loaded correctly, users must ensure that the packages referenced in those files are defined consistently at compile time and load time. Conforming programs must satisfy the following requirements:
  1. The current package when a top level form in the file is processed by 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:
    1. Any top level form in a file that alters the current package must change it to a package of the same name both at compile time and at load time.
    2. If the first non-atomic top level form in the file is not an 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.
  2. For all symbols appearing lexically within a top level form that were accessible in the package that was the current package during processing of that top level form at compile time, but whose home package was another package, at load time there must be a symbol with the same name that is accessible in both the load-time current package and in the package with the same name as the compile-time home package.
  3. For all symbols represented in the compiled file that were external symbols in their home package at compile time, there must be a symbol with the same name that is an external symbol in the package with the same name at load time.

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.