/ CASE STUDY
/ The Compiler
We have just described how a source program is translated into an internal representation. We now discuss how to translate the internal representation into a target program.
The predicate Translate(Program) is invoked in the root clause of the specification. The whole program is merely represented as a simple procedure without parameters. Hence, we can simply use Procedure to process the given abstract syntax tree. Before calling Procedure, we initialize the current nesting level of procedures (which is implemented as a global variable). After generating the code, we invoke emit to write it to the target file.
The predicate Procedure(Proc) handles a single procedure declaration the abstract syntax of which is
dcl(Ident, proc(Formals, Locals, Body), Pos)The procedure has a name given by Ident; formal parameters and local declarations are given by Formals and Locals; the procedure body is given by Body.
First, the current procedure nesting is updated accordingly. It is reset to its old value at the end of the rule.
During the processing of Body and local procedures, the formal parameters and the local declarations must be accessible. Hence, they are made visible by processing Formals and Locals with the predicate DeclareList. Outside the given procedure, the formal parameters and local declarations cannot be used. Hence, they are made invisible again ( UndeclareList) after processing the body and the local procedures.
DeclareList (to be discussed later) has additional parameters: DeclareList(X, Loc -> Size) indicates that the items in X are stored from location Loc and that they occupy Size units.
The stack frame of the procedure is organized as follows: 3 units for administrative data (static link, dynamic link, return address), SizeFormal units as to store parameters, and SizeLocals units to store local variables.
The target code of the procedure is given as follows:
ENT(SizeLocals) Code of body RET Code of local procedureThe code for the body is generated by the predicate Statement, the code for the local procedures is generated by LocalProcedures.
LocalProcedures(Decls) invokes LocalProcedure for each element of the declaration list( Decls).
If LocalProcedure(Decl) is invoked with a procedure declaration, it processes this declaration. Otherwise the passed element is skipped. A procedure is processed by Procedure (in the case of a local procedure, we first emit a start label).
We now refine the processing of procedure bodies. We discuss statements, expressions, and designators.