Jump to content

Page:AITR-474.djvu/74

From Wikisource
This page has been proofread, but needs to be validated.
64
F. Code generation

Given the foregoing analysis, the generation of code is straightforward, and largely consists of using the information already gathered to detect special cases. The special cases of interest relate almost entirely to function calls and closures (indeed, there is little else in the language for RABBIT's purposes!).

RABBIT has provision for "block compiling" a number of functions into a single module. This permits an optimization in which one function can transfer control directly to another without going through the "UUO handler". Even if several user functions are not compiled into a single module, this is still of advantage, because a single user function can produce a large number of output functions, as a consequence of the code-generation techniques.

A module consists of a single MacLISP function whose body is a single PROG. This PROG has no local variables, but does have a number of tags, one for each function in the module. On entry to the module, the register **ENV** will contain the "environment" for the function to be executed. As noted above, the format of this is arbitrary. For functions compiled by RABBIT, this is a list whose car is a tag within the PROG and whose cdr is the "real environment". {Note Code Pointers} At the beginning of the PROG there is always the code

(GO (PROG2 NIL (CAR **ENV**)
           (SETQ **ENV** (CDR **ENV**))))

the effect of which is to put the "real environment" in **ENV** and then perform a computed GO to the appropriate tag. (This is the only circumstance in which the MacLISP PROG2 and computed GO constructs are used by RABBIT-compiled code. Either could be eliminated at the expense of more bookkeeping, the former by