.c	Friday  Dec 2,1983  1:49  LQ+4D.19H.56M.1S.  -*- Bolio -*-


.chapter "Compilation"

term_i{Compilation} is essentially the process of translating from
one specification into another which is presumably more efficient, and
probably more low-level in
some respects.  The lan{nil} compiler translates lan{lisp} code
into the lan{vax} instructions necessary to execute that code;  some
of these instructions may perform the task directly, while others may
call functions or lan{nil} kernel subroutines to do it.  In any
event, the end result is intended to exclude the lan{nil}
interpreter from the running of the program.  The lan{nil} compiler
does not output lan{macro32} code or anything of the sort;  rather,
it represents the code and data itself, and assembles the code,
lan{lisp} objects referenced by the code, and whatever other
information is needed to help construct that data, into a
term_i{compiled code module}.  This is what the 3module* data
type represents.

When the lan{nil} compiler compiles a file, it first establishes the
proper environment for the compilation, as specified by the file's
attribute list (described in (file-attribute-list-section-page)).
That done, it reads and processes each form in the file.  What it does
with each form depends on what the form is.
.table 7 250 250
.item (declare 2declarations*)
'findex declare
The 2declarations* are processed, and take effect for at least the
remainder of the compilation.  (lan{nil} often makes the
declarations globally right now;  they might remain after the
compilation, but usually they do not.)
.item (eval-when 2kwd-list* 2forms*...)
'findex eval-when
If 3compile* is a member of 2kwd-list*, all of the 2forms*
are evaluated then and there.  Then, if 3load* is a member of
2kwd-list*, the 2forms* are recursively processed.
.item (progn 2forms*...)
2forms* are recursively processed.  Note that this is identical to
3(eval-when (load) 2forms*...)*, and upwards-compatible with
3(progn 'compile 2forms*...)*.
.item (compiler-let 2bindings* 2forms*...)
Establishes the bindings specified by 2bindings*, then recursively
processes 2forms* in that environment.  See (compiler-let-fun).
.item (defun 2name* 2arglist* 2etc*...)
.item1 (defun (2name* 2property-name*) 2arglist* 2etc*...)
'findex defun
The function is compiled, and the appropriate assignment (function
cell or 3putprop*) will be put in the compiler's output file.
.item (defmacro 2name* 2etc*...)
.item1 (macro 2name* 2lambda-list* 2etc*...)
The specified macro definition for 2name* is added to the
compilation environment.  Then, the macro is compiled, so will be
there when the compiled output file is loaded.  It may not be depended
on that 2name* is defined in the lan{lisp} environment itself;
only that code being compiled will have the macro run to produce the
expansion.  If it is necessary for the macro to actually be defined
(perhaps in order for it to be called from within other macros, as
opposed to just expanded in code being compiled), then the
3defmacro* or 3macro* form should be enclosed within an
3(eval-when (compile ...) ...)* form.
.item (defun 2name* macro 2lambda-list* 2etc*...)
The compiler whines at you and turns this into 3macro*.  This is
provided to catch old lan{maclisp} code which should probably use
3defmacro* (or at the very least 3macro*) instead.
.item (defun 2name* fexpr 2lambda-list* 2etc*...)
The compiler barfs at you and turns this into a special form
definition.  Calls to it from compiled code will not work.  If
2name* is only around for users to call interactively, however, it
might just function properly.  This is provided only to brute-force
through some lan{maclisp} programs.  Generally, special forms or
term_i{fexprs} should be rewritten as macros.
.item (defun 2name* 2atom* 2etc*...)
The function definition is assumed to be a lan{maclisp} 3lexpr*.
'cindex lexpr
It is transformed appropriately, and compiled, after the compiler gets
through giving you a hard time.
.item (defflavor 2etc*)
Code to perform the flavor definition at load time is generated.
Additionally, declarative information is added to the compilation
environment so that 3defmethods* will compile correctly, and the
routines defined for the 3:outside-accessible-instance-variables*
can be compiled correctly.
.item (defmethod 2etc*)
Compiles the code for the defmethod.
.item 2anything-else*
If 2anything-else* is a macro call or a call to a function the
compiler has special rewrite information about, the macro expansion or
rewrite is performed, and the compiler tries again.  Otherwise,
2anything-else* will be evaluated at load time.  Currently this is
done by compiling the expression, which eliminates load-time
dependencies upon macros.
.end_table
There are various other forms which implicitly do compile-time
processing by virtue of how they are defined, rather than by the
compiler recognizing them specially.  For instance, 3defstruct*
(currently) by default expands into the appropriate macro, function,
and data definitions, inside of an 3eval-when*.  For this reason,
the above list cannot be taken as being all-inclusive.

.defun compile-file input-file &key :package :set-default-pathname :output-file :default-pathname :defaults
Compiles 2input-file*, storing the vasl file in 2output-file*.

If 2package* is specified, then the file is read in in that
package, in spite of what might be specified in the source file
property list (see (file-property-list-section-page)).

The 2input-file* is defaulted from the 2default-pathname* if any,
and then from 2defaults*, which should be a pathname defaults.  If
2set-default-pathname* is not (false), then the default pathname
of 2defaults* (which defaults to the value of
3*load-pathname-defaults**, (*load-pathname-defaults*-var)) is
updated.

2output-file* defaults to 2input-file* with a 3vasl* file
type (lan{vms} extension of 7VAS*).

By special dispensation (to those of me who cannot get out of the
habit of using this feature), if exactly two arguments are given to
3compile-file*, then the first is the input file and the second is
the output file.  This is typically used like
.lisp
(compile-file "[nil.io]iofun" "[nil.vas]")
.end_lisp
.end_defun


.defun comfile ...
Alternate name for 3compile-file*. lan{Common lisp} defines the
use of the name 3compile-file*, but not 3comfile*, for
whatever that is worth.
.end_defun


.defun compile function
Compiles the interpreted (and in-core) definition of 2function*,
in-core.  That is,
.lisp
(defun fact (x)
  (if (zerop x) 1 (times x (fact (sub1 x)))))
(fsymeval 'fact)
  => #<Interpreter-Closure FACT 0 123456>
(compile 'fact)
(fsymeval 'fact)
  => #<SUBR FACT>
.end_lisp
In fact, what happens is that the 2function* is compiled into a
temporary file and that file loaded;  this is somewhat of a kludge at
the moment, but is done because of limitations of the lan{nil}
module assembler.  Note in this regard 3user-scratchdir-pathname*
((user-scratchdir-pathname-fun)) and
3*scratch-pathname-defaults**
((*scratch-pathname-defaults*-var)).

The above described calling sequence is the intersection of what is
provided now, and what lan{common lisp} defines for 3compile*.
.end_defun


.defspec compiler-let ({(var val)}*) {form}*
When evaluated, this binds 2dynamically* each 2var* to the
evaluation of each 2val*, and then evaluates the 2form*s in
that environment.  Syntactically, this is like 3let* and
3let** ((let-fun)).  At this time, there is no guarantee as to
whether the variables are bound in parallel or sequentially, however.

When compiled, however, the binding evaluation of the 2val*s and
binding of the 2vars* is done at 2compile* time, and then the
2form*s (as a 3progn*) compiled in that environment.  This is
one way to communicate information to the compiler and to macro
functions, and is the only way to set certain compiler switches
locally right now.

3compiler-let* is handled properly as a toplevel form in a file,
and is properly tranparent to things like special predicate
compilations.

Most of the variables which 3compiler-let* used to be useful for
have be excised from lan{nil}, primarily because the primitives they
controlled the compilation of have become more generic due to the
implementation of lan{common lisp} arrays.  The only two such
variables left are var_i{compiler:*open-compile-carcdr-switch} and
var_i{compiler:*open-compile-xref-switch}, and these are now
obsoleted by use of the 3optimize* declaration.
3compiler-let* is still useful, of course, for communication
between macros, and that is its intended use anyway.
.end_defspec


.section "Belling the Compiler"

.subsection "Declarations Affecting Compilation"
.setq compilation-declarations-section-page section-page

.cindex optimize declaration
The lan{nil} compiler now recognizes the lan{common lisp}
3optimize* declaration.  This declaration looks like
.lisp
(declare (optimize (speed 3) (space 0)))
.end_lisp
There are four different qualities which may be optimized:
3speed*, 3space*, 3safety*, and 3compilation-speed*.
Each may have specified for it an integer value from 0 to 3
(inclusive);  0 means that that consideration should be effectively
ignored, and 3 means that it is very important.  
The default value for each is 1.  Basically, these
quantities are used to aid the compiler in how to make tradeoffs
during the compilation.  (The one which the current lan{nil}
compiler ignores totally now is 3compilation-speed*.  The future
smarter one will need to recognize it.)

As an example, the setup to do a function call (and a few other
things) has to push a block of things onto the stack.  The values of
the 3speed* and 3space* qualities are used to decide which of
a few different methods should be used to do this.  For function call
setup in particular, the 3safety* quality is examined to determine
whether or not special markers should be used in the call frame so
that the debugger can tell which arguments have been computed, should
an error occur (it is somewhat easier to push zeros than something
else).

Similarly, various functions can often be compiled with various
degrees of safety, and the decision might involve space and time
tradeoffs.  The compilation of 3car*, 3cdr*, all of their
compositions, and their updates (3rplaca*, 3rplacd*, or use
with 3setf*), are normally compiled as special subroutine calls
into the lan{nil} kernel;  these perform error checking, but leave
out the extra function-call overhead.  If one cranks up the
3speed*, however, and does 2not* crank up the 3safety*,
then the compiler can pretty simply code out the instructions itself.
The same goes for the access of components of a
3defstruct*-defined structure (of the normal 3:named*, i.e.,
typed, kind), and a number of other functions.

.defvar compiler:*open-compile-carcdr-switch
If this is not 3nil*, then the compiler always inline-codes
3car*, 3cdr*, and all their compositions and updates, as just
the instructions needed to perform those operations, without any type
checking.  Otherwise, it heeds the values assigned to the various
optimization qualities as described above.

This should be considered obsoleted by the use of the 3optimize*
declaration.
.end_defvar

.defvar compiler:*open-compile-xref-switch
This switch controls whether the 3si:xref* ((si:xref-fun))
function is totally open-compiled.  This function is what is used for
accessing components of 3defstruct*-defined structures (of the
default 3:named* variety), outside-accessible instance variables
(see 3defflavor*, (defflavor-fun)), and a few other things.
If this switch is not 3nil*, then calls to 3si:xref* and its
update function are always open-compiled;  otherwise, the values
assigned to the various optimization qualities described above are
heeded.  "Not open compiling" 3si:xref* makes a subroutine call to
the lan{nil} kernel, not a function call, so it is still not
particularly slow.

This is obsoleted by the 3optimize* declaration.
.end_defvar

Two other declarations which can affect the speed, space, and safety
'cindex inline declaration
'cindex notinline declaration
of compiled code are the 3inline* and 3notinline*
declarations.  These look like
.lisp
(declare (notinline car cdr) (inline keywordp))
.end_lisp
and direct the compiler to specifically inline-code (or not
inline-code) specific functions.  As of this writing, the lan{nil}
compiler recognizes these declarations and then ignores them.  It is
possible that by the time this lan{nil} is released, the compiler
will heed the 3notinline* declaration in a fairly general fashion,
and completely inhibit inline compilation of the specified functions.
This particular compiler, however, will normally inline code (possibly
by rewriting) anything it knows how to, so 3inline* will only be
useful for shadowing a 3notinline* declaration.

There are two likely reasons for desiring that a function not be
inline coded.  First, if it is coded as a function call, then it can
be traced (see 3trace*, (trace-fun)).  One could compile
(perhaps incrementally, from the editor) just a
small number of functions inhibiting inline compilation of some other
function, in order to track down and trace some anomalous behavior
which is not easily trackable by the normal error-checking performed.
A possible second reason to inhibit inline compilation is if the
compiler does not heed the 3optimize* declaration reasonably for
that particular function, and one requires the extra error-checking
which would be performed by the normal function entry.

.subsection "Interaction Control"

.defvar compiler:*messages-to-terminal?
If this is not 3nil*, then the compiler (3compile-file* and
3compile*, and even the lan{lsb}-defined function 3lsbcl*
ref{LSBMan}) will print out verbosely on the terminal.  If it is
3nil*, nothing will be printed, unless errors occur, which is a
separate can of worms.  By default, this is 3t*.
.end_defvar

