Book
reviews
259
Edsger W. Dijkstra and Care1 S. Scholten, Predicate Cuicdus and Program Semantics, Texts and Monographs in Compeer Science (Springer, Heidelberg, 1989), Price 78.00 DM (hardback), ISBN 3-540-96957-8. The objective of this book is to present a formal theory of predicate transformers starting completely from scratch. The authors have been uncompror;lising in their treatment of this theory, developing the notations, tools and results as needed in a logical manner. As a consequence of the authors’ views on foundational issues, predicate transformers are placed center stage; they emerge naturally out of the reworking of the predicate calculus given early on. The claim is that this re-evaluation of so fundamental a tool as the predicate calculus is justified by the need to explain the notational shorthand they use to describe properties in terms of predicates. The authors are justifiably proud of the calculation style of proof, which they attribute in the preface to W. H. J. Feijen. This is due to the considerable economy of presentation that they have managed to achieve, whilst also remaining rigorous. At first, I found it a little awkward to read, but after some practice, it eventually clicked. However, I feel that there are some problems lurking in this notation, mainly concerning reasoning in the presence of local assumptions and hypotheses. It may be argued that this is merely a scoping issue, one which is usually remedied in conventional logic by the use of sequents, or a similar device. One of the major triumphs of this book is the presentation of the observation that unbounded nondeterminism may be justified by using a semantics that is monotonic but not necessarily or-continuous. This is probably fairly well-known to theorists (re: David Park’s work on the semantics of fair parallelism) but perhaps less so amongst computer scientists in general. This justification hinges upon the use of general well-founded orderings, those going beyond the natural numbers (w) but presumably less than eo, in ordinal terms. Also, the authors claim to have avoided the use of “transfinite induction”. Instead, I feel that they have cleverly smoothed its use, by being careful to only mention well-founded relations and to avoid any discussion of the ordinals directly. The authors are also proud of the lack of operational bias in their treatment of predicate transformers. They present their calculation view as being developed independently of the world of electronic computers. It is only in Chapter 10 that the theory and semantics developed in earlier chapters is used to provide a somewhat more operational interpretation. Even then, very little operational intuition concerning mechanism is required in order to understand this chapter. Unfortunately for those who might be interested, this also means that little operational intuition is conveyed either. The main difficulty with this book concerns the amount of mathematics needed to read it. Unlike most mathematical texts which have positive pre-requisites, this one almost requires that you know next to nothing (or at least are prepared to forget what you know). For example, I mentioned above that a vital step in the book is the development of a notational variant of the predicate calculus. This places great
Book reviews
260
emphasis on universal statements-statements that are everywhere true about a boolean struture. Well, you might say, surely this means the same as being valid. And indeed, you would (I think) be quite correct. This is just one of several places where the authors have ignored conventional terminology and ideas in favour of their own. What is unpalatable about this is that the authors make no concessions to those who are unfortunate enough to have some understanding of the subject already. Now we approach the heart of this book-the way that logic itself is treated and the consequences that this has for the presentation of program semantics. Quantifiers are introduced very early on (page 15), to make them part of the conceptual furniture so to speak, in the earnest hope that the reader could almost forget them later. Some classic pitfalls-those involving the rules for free and bound variables-are avoided by pointing out the syntactical nature of the problem (i.e., that the result should be independent of the name of the dummy variable used). This, of course, is not new-1 remember being given similar advice in my first course on integration at school. However, by impressing this point on the reader early on, the authors serve notice that the reader will be obliged to engage in this name changing procedure whenever it becomes necessary (again, just as in calculus). However, as anyone who has implemented substitution for theorem proving systems will testify, this process can be fairly subtle when used in practice. The authors have intentionally left this for the reader to resolve, on the assumption that the reader is sufficiently skilled to know when this is necessary. I think that the main innovation in logic notation is the authors’ use of what they call the everywhere operator, which is attributed to A. J. M. van Gasteren. As observed earlier, my understanding is that this captures the traditional concept of validity. The introduction of this operator does initially cause some pause for thought, since abuse of this notion easily leads to unsound systems. After getting over the initial surprise, it seems that this treatment is sound. Since the authors do not offer any kind of soundness argument, the best that can be said is that there are no obviously unsound statements, even though some “equations” do seem odd, at first glance:
[(X Y)l=[Xl~[Yl. This says that a pair of boolean statements shown to be valid will each be independently valid. As I have already said, I think what FF&~ easily make this book hard to read by computer scientists will be any conventional background in logic, algebra, and lattice theory that they may have. A potential disadvantage for a beginner in reading this book before other works on program semantics is that they may not help in making the work of others any easier to understand; I suppose it is a moot point whether this is acutally a disadvantage or not. In any case, as the authors have made so little
Book reviews
261
reference to other related work and also have so comprehensively and uncompromisingly used their own notations, even for logic, they have made it unnecessarily awkward to show how these ideas fit into the general scheme of things. This feeling of isolation is not at all helped by the complete absence of bibliographical information, with the exception of a citation to Boole’s Laws of Thoughr on page 6 and the naming of the Knaster-Tarski lemma. Do we take from this that there have been no other works in logic of relevance or worthy of mention since Boole? In my view, this is a serious omission and is hardly excusable, especially for authors of such eminence. Much is made of the importance of notation, and this book adds its fair share. Initially, I was unhappy with some unconventional choices-such as giving A and v the same syntactic precedence. But even these initial surprises were soon overcome, after the logical rationale for the choices was noted. However, the typographical choice of using extra white space to mark the presence of mathematical text is possibly less well advised. With regard to the need for new notation, a problem can only be potentially significant and interesting whenever it continues to manifest itself no matter what notation it is expressed in. As there are plenty of interesting problems around, mere choice of notation has clearly failed as a method for solving problems! In this contex&, mathematicians and computer scientist are, perhaps unconsciously, selecting notations which avoid introducing “problems” arising as a result of a poor choice of syntax. Of course, compromise will often be inevitable, in which case other criteria would doubtless intervene, such as economy of expression and orthgonality of concept. By changing notations around, the authors succeed., in my view, in provoking the reader into seeking out those aspects that remain unchanged, in a search to establish connections with what the reader already understands. This tactic can have the result of turning the gaze of diligent and knowledgeable readers to subtleties often missed otherwise. Notational change can therefore have other beneficial effects, such as forcing the reader to re-examine even familiar ideas from a different point of view. But is this a sufficient payoff? I suspect that the authors might well argue that the real payoff lies in the simplification afforded by their notation over others (a clearly subjective claim). Well, I certainly agree that this work provides an elegant way to manipulate predicate transformers. As in everything, such an economy is bought at a price. I feel that this price is associated with the fact that notions of data structure and data type are not discussed in any depth. It is perhaps understand able that this was not included, because the message of this book, i.e., programmi% as the manipulation ofpredicate trunsjbmers might have been considerably diluted and obscured if it had. Even so, it might have been helpful to at least allude to the issues involved in using more expressive data structures than the humble variable and array over integer and boolean values. The world of programming is now rich in structure in terms of both data types and progr:*m control. The lack of reference
262
Book reviews
to this richness seriously undermines any appeal that the book would have for practitioners. It is not easy to describe the readers who will gain most from reading this book. For instance, it does not contain a range of radically new theorems about advanced topics in program semantics or a comprehensive reference work that covers known semantic techniques. To the authors’ credit, the preface essentially says it was not intended to be either of these things. To briefly summarise, this book succeeds in offering an alternative presentation of logic au -’ qredicate based program semantics, from a distinctive, thought-provoking point of view. As such, it is perhaps of greatest relevance to those with a serious interest in presentations of program semantics and underlying theories.
Brian MONAHAN Department of Computer Science University of Manchester Manchester, United Kingdom
Peter Lee, Realistic Compiler Generation (MIT Press, London, 1989), Price $43.95 (hardback), ISBN O-24%12!11-7.
This book is a revised version of Peter Lee’s doctoral dissertation, completed under the supervision of Uwe Pleban at the University of Michigan. Lee’s thesis is that realistic compilers can be generated from denotational semantic specifications, provided that the latter are well structured for the purpose. “Traditional” (Oxford-style) denotational specifications are not well structured, as Lee convincingly demonstrates. They specify mappings from programs to A-expressions, which must then be evaluated using P-reduction. This is very expensive, whether evaluation is done entirely at run-time or partial evaluation is done at compile-time, because of the large number of closures present. “Classical” semantic-directed compiler generators, such as Mosses’ SIS, Paulson’s PSP, and Wand’s SPS, are therefore prohibitively inefficient. Lee argues that this inefficiency is inherent. He also picks up and amplifies Mosses’ argument that traditional denotational specifications are badly structured in another sense: they are difficult to read, to write, and to modify. Small extensions to the specified language often entail a change in the semantic mooel, forcing the entire specification to be rewritten. For example, adding loop exits would force a direct-type semantics to be rewritten in the continuational style. Lee’s proposal is to separate a language’s semantic specification into two levels, the macro-semantics and micro-semantics. The interface between these levels is a semautic algebra. whose sorts might include: