We consider the problem of automatically deriving correct compilers from relational semantic specifications of programming languages. A relational semantics is an assignment of initial-state final-state relations (defined by means of proof rules) to programs. Compilers are generated in three steps. First, the language definition is transformed into a stack semantics in which the sto~age of semantic values is made explicit. Next, stack rules are assembled into a socalled language scheme containing exactly one rule for each language construct. We consider languages for which non-deterministic branches may be replaced by deterministic ones. Finally, rules are expanded for the purpose of recursion detection, thus obtaining schemes which may be used for code generation in a syntax-directed compiler.
I. IntroductionIn this paper we consider relational semantic specifications of programming languages and the problem of deriving correct compilers from such specifications in an automatic way. In relational semantics meaning is given to programs as relations between initial and final states. The term "relational semantics" seems to have originated with the relational theories of Hoare and Lauer in [Hoare/ Lauer 73]. Their semantics, however, have a much less operational flavour than the one considered here, in that they e.g. use invariant properties for the semantics of loops. Our relational semantics is much closer to the deductive systems proposed by Greif and Meyer ([Greif/Meyer 81]) as an alternative to the semantics of Hoare and Lauer. Also Plotkin proposed the use of relational semantics in his work on structural operational semantics ([Plotkin 81]), and in fact our understanding of relational semantics has been heavily influenced by his work.