using a temporary intermediate variable, the latter by using a giant COND with
non-computed GO statements (which is effectively how the MacLISP compiler
compiles a computed GO anyway). As always, such trivial issues are left to the
MacLISP compiler when they do not bear on the issues of interest in compiling
SCHEME code.) For small functions, often the "main entry point" is the only
closed function, and it would be possible to eliminate the computed GO, but
RABBIT always outputs one, because is is cheap and provides a useful error check.
Once the computed GO has been performed, the code following the tag is
responsible for performing its bit of computation and then exiting. It may exit
by setting the **FUN** register to another function, setting up appropriate
argument registers, and then doing (RETURN NIL) to exit the module and enter the
UUO handler; or it may exit by directly transferring control to another function
within the module by performing a GO to the appropriate tag, after setting up the
arguments and **ENV**. In the latter case the arguments may actually be passed
through "memory locations" rather than the standard "registers". (Conceptually,
in this optimized case the environment needed for the function being called is
being passed, not in **ENV**, but spread out in those registers and locations
lower than those being used to pass the arguments.)
Starting with the CPS version of one or more user functions, the generation of the code for a module proceeds iteratively. Code for each function is generated in turn, producing one segment of code and a tag; this tag and code will become part of the body of the module. In processing a function, other functions may be encountered; in general, each such function is added to the list of outstanding functions for the module, and is replaced by code to generate a closure for that function. when all functions have been processed, the outer structure of the module is created.
Many situations are treated specially. For example,