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


Here is a draft of another proposal dealing with what the compiler may
"wire in" to the code it is compiling.  It is roughly based on a
section of RAM's well-known "Compiler Cleanup Proposal #3", with a
couple of additions and some changes in terminology.  It's my
impression that most implementations are already pretty close to this
proposal, but if I'm wrong and there's something that's going to give
you grief, speak up!


References:	CLtL p. 143, 321
		RAM's "Compiler Cleanup Proposal #3"
Edit History:   V1, 2 Sep 1988, Sandra Loosemore (initial draft)

Problem Description:

CLtL does not clearly specify what aspects of the compiletime
environment the compiler (or other preprocessor) may "wire in" to code
being compiled.


Common Lisp deliberately leaves unspecified the time at which certain
transformations, such as macro expansion, are performed within a
program.  While some implementations perform such transformations
concurrently with evaluation, it is also legitimate to perform
transformations during a preprocessing phase.  For example, an
implementation might choose to apply transformations at "function
promotion time" (i.e., transformations are applied once during
evaluation of a surrounding FUNCTION special form), or to completely
transform each top-level form and all of its subforms before
performing any evaluation.  User programs cannot portably depend upon
either the time of such transformations, or the number of times the
transformations are applied.

In all cases, however, compiling a program (with COMPILE or
COMPILE-FILE) provides a mechanism for forcing these transformations
to be applied and a guarantee that, once compiled, no further
transformations will be applied to that program.

In the discussion that follows, the term "compiler" is to be understood
to include other preprocessors as well.  Likewise, the "compiletime
environment" refers to the environment in which program transformations
occur, while "runtime" refers to the time the program is executed.

(1) The following information *must* be present in the compiletime
environment for the preprocessor to apply the correct transformations.
This information need not also be present in the runtime environment.

    (a) Macro definitions must be available in the compiletime environment.
	The compiler may assume that forms that are lists beginning with
	a symbol that does not name a macro or special form is a function
	call.  (This implies that SETF methods must also be available at

    (b) Special variables must be declared as such before they are bound.
	The compiler must treat any undeclared variable binding as a
	lexical binding.

(2) The compiler *may* assume that, if any of the following kinds of
information is present in the compiletime environment, the same information
will also be present in the runtime environment.  In all of these cases,
the absence of the information at compiletime is not an error, but its
presence may enable the compiler to do a better job.

    (a) The compiler may assume that functions which are defined and
	declared INLINE in the compiletime environment will retain the
	same definition in the runtime environment.

    (b) The compiler may assume that, within a named function, a
	recursive call to a function of the same name refers to the
	same function, unless that function has been declared NOTINLINE.

    (c) The compiler may assume that the signature of all built-in 
	Common Lisp functions will not change.  In addition, the compiler 
	may treat all built-in Common Lisp functions as if they had been
	proclaimed INLINE.

    (d) The compiler may assume that symbols which have been defined as
	constants (using DEFCONSTANT) in the compiletime environment
	will retain the same value in the runtime environment.

    (e) Types that are defined with DEFTYPE or DEFSTRUCT can be assumed to
	retain the same definition in the runtime environment as in the
	compiletime environment.  (Note that it is not an error for an
	unknown type to appear in a declaration at compiletime, although
	it is reasonable for the compiler to emit a warning in such a

    (f) The compiler may assume that type proclamations for global 
	variables and functions which are present in the compiletime
	environment will also be present in the runtime environment.

(3) The compiler *must not* make any additional assumptions about
consistency between the compiletime and runtime environments.  In 

    (a) The compiler may not assume that functions that are defined
	in the compiletime environment that have not been declared
	INLINE, other than built-in Common Lisp functions, will retain
	either the same definition or the same signature at runtime.
	It is, however, reasonable for the compiler to emit warning 
	messages about calls to functions that are defined in at
	compiletime, but where the wrong number or type of arguments
	are supplied.



This proposal generally reflects current practice.

Current Practice:

I know of no compiler that does not implement the provisions of item (1).

For item (2), most compilers (including Lucid) optimize self-recursive
calls by default.  Most compilers also opencode data structure
accessors (such as CAR) at some level of optimization, and some code
much more complicated built-in functions inline as well.  VaxLisp, for
example, normally compiles MEMBER inline.  The Lucid compiler makes
use of type declarations to perform generic-to-specific
transformations on many arithmetic and sequence functions, which is
also a form of inlining.

Cost to implementors:


Cost to users:

Since most implementations appear to be largely in conformance with the
proposal, users should notice little difference.


The presence of a definite specification of what may happen when will
help users structure their programs so they will compile correctly in
all Common Lisp implementations.


Does anything need to be added to cover interaction between the compiler
and CLOS?