which never appears in an ASET'), a property KNOWN-FUNCTION is put on its
property list whose value is the node of the CPS version of that function. This
property is used later in generating code for combinations in whose function
positions such variables appear.
The third pass (DEPTH-ANALYZE) examines each LAMBDA-expression and
determines the precise registers or memory locations through which arguments are
to be passed to each. Closed functions take their arguments in the standard
registers described earlier; non-closed functions may take their arguments in
any desired places. (Partially closed functions could also, but there is little
advantage to this.) The allocation strategy in RABBIT for non-closed functions
is presently merely stack-like; the deeper the nesting of a function, the higher
in the ordering of "registers" and "memory locations" are the locations assigned.
(See e.g. [Johnsson] for a detailed analysis of the register allocation problem.)
The fourth pass (CLOSE-ANALYZE) determines the precise format of the
environment to be constructed for each closure. That is, while the third pass
handles cases for which stack-allocation of environments will suffice, the fourth
pass deals with heap-allocated environment structures. Recall that the format of
an environment can be completely arbitrary, since the only code which can
possibly refer to an environment is the function for a closure of which the
environment was created. Therefore the compiler which compiles that function has
a free hand in determining the structure of the environment. For the sake of
simplicity, RABBIT chooses to generate code which represents environments simply
as a list of variable values. Several environment lists may share a common tail.
The environment for a closure need not contain any variables not needed by the
closed function, but it may if this will allow the sharing of a single structure
among several closures. (There is a problem with variables modified by ASET'
which is discussed in the next paragraph.)