The first LISP compiler was implemented very early in the life of
the first LISP, LISP I for the IBM 704.
The LISP I Compiler
From the LISP I Programmer's Manual (March 1, 1960)
section 4.2, "Definitions of Functions in LISP"
In Chapter 2 functions are connected to their names only through the
use of the form LABEL. In the current LISP system, there are two
further ways a function can be defined:
The first of these relates to functions defined in the system by
machine-language subroutines. Such a subroutine for a function may
be already available as part of the LISP system itself, in which
case it appears among the functions given in Section 9, or it may
have been produced by the LISP compiler.
Section 4.6, "The Compiler," describes its operation in detail:
The LISP compiler is itself a pseudo-funciton which is available to
the APPLY operator. The compiler is called in by the LISP function,
comdef[x],
where x is a list of names of the functions to be compiled. Each
function on the list will be compiled into a binary machine
program....
The compiler runs in several stages: producing a (LISP) list of
assembly instructions, a two-pass assembly of this list to binary
code, and then binding the name in the system so it calls the
machine-language code rather than the original S-expression. The
assembly code list looks like:
(( ,LXD,0,4),( ,TXI,G0007,4,-1),( ,TRA,*+5),(G0008,BSS,0),...)
This appears also to be the first use of something like
gensym
: "In this example, the objects beginning with G are
atomic symbols generated for use within the compiler."
"Linking" was done at compile time, so one had to be careful of order
when compiling functions in separate comdef
s, though circular
references were fine if done within a single compile run:
If a function f uses a function g as a subfuction, then g should be
included in a comdef which comes before the comdef involving f
except in the following special case: if a closed circle of
function usage occurs, e.g.
f₁ uses f₂
f₂ uses f₃
.
.
.
fₙ uses f₁,
then all of the functions in this circle must be compiled in the
same comdef. thus the functions listed in a given comdef should
be unrelated or related in this circular sense.
The LISP 1.5 Compiler
The compiler was actively maintained and extended for at least several
years. AIM-039, "Artificial Intelligence Project--RLE and MIT
Computation Center Memo 39--The New Compiler," by T. Hart and M. Levin
has no date, but from its sequence in the AIM list it
appears to have been written sometime between January 1962 (AIM-31)
and October 1962 (AIM-46). By this point the compiler had become
self-hosting:
This memo introduces the brand new LISP 1.5 Compiler designed and
programmed by Tim Hart and Mike Leven. It is written entirely in
LISP and is the first compiler that has ever compiled itself by
being executed interpretively.
The purpose of the LISP Compiler is to replace S-expression
definitions of functions with efficient machine language
subroutines. A subroutine can be expected to run about 40 times as
fast as the interpreter can execute the same function from its
S-expression definition. Subroutines typically take 70-80 per cent
of the storage required by their corresponding S-expressions.
The compiler as it exists on the standard compiler tape is a machine
language program that was obtained by having the S-expression
definition of the compiler work on itself through the interpreter.
The compiler is designed so that compiled functions and interpretal
[sic] functions can be intermixed freely. Suitable declarations
allow free variables to be transmitted between the compiled
functions and the interpreter.
There were some interesting limitations to the compiler, perhaps for
performance reasons. For example, checks for the existence of free
variables used by the compiled functions seem to have been left out.
From section "Free Variables":
When a variable is used free, it must have been bound by a higher
level function. If a program is being run interpretively, and a free
variable is used without having been bound on a higher level, error
diagnostic *A 8* will occur.
If the program is being run compiled, the diagnostic may not occur,
and the variable may have value NIL.
All free variables in compiled programs must be declared SPECIAL or
COMMON.