Team-Fly Concepts in Programming Languages by John C Mitchell ISBN:0521780985 Cambridge University Press © 2003 (529 pages) This book provides a better understanding of the issues and trade-offs that arise in programming language design and a better appreciation of the advantages and pitfalls of the programming languages used Table of Contents Concepts in Programming Languages Preface Part - Function and Foundations Chapter - Introduction Chapter - Computability Chapter - Lisp—Functions, Recursion, and Lists Chapter - Fundamentals Part - Procedures, Types, Memory Mangement, and Control Chapter - The Algol Family and ML Chapter - Type Systems and Type Inference Chapter - Scope, Functions, and Storage Management Chapter - Control in Sequential Languages Part - Modularity, Abstraction, and Object-Oriented Programming Chapter - Data Abstraction and Modularity Chapter 10 - Concepts in Object-Oriented Languages Chapter 11 - History of Objects—Simula and Smalltalk Chapter 12 - Objects and Run-Time Efficiency— C++ Chapter 13 - Portability and Safety—Java Part - Concurrency and Logic Programming Chapter 14 - Concurrent and Distributed Programming Chapter 15 - The Logic Programming Paradigm and Prolog Appendix A - Additional Program Examples Glossary Index List of Figures List of Tables Team-Fly Team-Fly Back Cover This textbook for undergraduate and beginning graduate students explains and examines the central concepts used in modern programming languages, such as functions, types, memory management, and control This book is unique in its comprehensive presentation and comparison of major object-oriented programming languages Separate chapters examine the history of objects, Simula and Smalltalk, and the prominent languages C++ and Java The author presents foundational topics, such as lambda calculus and denotational semantics, in an easy-to-read, informal style, focusing on the main insights provided by these theories Advanced topics include concurrency and concurrent object-oriented programming A chapter on logic programming illustrates the importance of specialized programming methods for certain kinds of problems This book will give the reader a better understanding of the issues and trade-offs that arise in programming language design and a better appreciation of the advantages and pitfalls of the programming languages they use About the Author John C Mitchell is Professor of Computer Science at Stanford University, where he has been a popular teacher for more than a decade Many of his former students are successful in research and private industry He received his Ph.D from MIT in 1984 and was a Member of Technical Staff at AT&T Bell Laboratories before joining the faculty at Stanford Over the past twenty years, Mitchell has been a featured speaker at international conferences, has led research projects on a variety of topics, including programming language design and analysis, computer security, and applications of mathematical logic to computer science, and has written more than 100 research articles His graduate textbook, Foundation for Programming Languages covers lambda calculus, type systems, logic for program verification, and mathematical semantics of programming languages Professor Mitchell was a member of the standardization effort and the 2002 Program Chair of the ACM Principles of Programming Languages conference Team-Fly Team-Fly Concepts in Programming Languages John C Mitchell Stanford University CAMBRIDGE UNIVERSITY PRESS Published by the Press Syndicate of the University of Cambridge The Pitt Building, Trumpington Street, Cambridge, United Kingdom Cambridge University Press The Edinburgh Building, Cambridge CB2 2RU, UK 40 West 20th Street, New York, NY 10011-4211, USA 477 Williamstown Road, Port Melbourne, VIC 3207, Australia Ruiz de Alarcón 13, 28014 Madrid, Spain Dock House, The Waterfront, Cape Town 8001, South Africa http://www.cambridge.org Copyright © 2002 Cambridge University Press This book is in copyright Subject to statutory exception and to the provisions of relevant collective licensing agreements, no reproduction of any part may take place without the written permission of Cambridge University Press First published 2002 A Typefaces Times Ten 10/12.5 pt., ITC Franklin Gothic, and Officina Serif System L TEX2ε [TB] A catalog record for this book is available from the British Library Library of Congress Cataloging in Publication data available 0-521-78098-5 Concepts in Programming Languages This textbook for undergraduate and beginning graduate students explains and examines the central concepts used in modern programming languages, such as functions, types, memory management, and control The book is unique in its comprehensive presentation and comparison of major object-oriented programming languages Separate chapters examine the history of objects, Simula and Smalltalk, and the prominent languages C++ and Java The author presents foundational topics, such as lambda calculus and denotational semantics, in an easy-to-read, informal style, focusing on the main insights provided by these theories Advanced topics include concurrency and concurrent object-oriented programming A chapter on logic programming illustrates the importance of specialized programming methods for certain kinds of problems This book will give the reader a better understanding of the issues and trade-offs that arise in programming language design and a better appreciation of the advantages and pitfalls of the programming languages they use John C Mitchell is Professor of Computer Science at Stanford University, where he has been a popular teacher for more than a decade Many of his former students are successful in research and private industry He received his Ph.D from MIT in 1984 and was a Member of Technical Staff at AT&T Bell Laboratories before joining the faculty at Stanford Over the past twenty years, Mitchell has been a featured speaker at international conferences; has led research projects on a variety of topics, including programming language design and analysis, computer security, and applications of mathematical logic to computer science; and has written more than 100 research articles His previous textbook, Foundations for Programming Languages (MIT Press, 1996), covers lambda calculus, type systems, logic for program verification, and mathematical semantics of programming languages Professor Mitchell was a member of the programming language subcommittee of the ACM/IEEE Curriculum 2001 standardization effort and the 2002 Program Chair of the ACM Principles of Programming Languages conference Team-Fly Team-Fly Preface A good programming language is a conceptual universe for thinking about programming Alan Perlis, NATO Conference on Software Engineering Techniques, Rome, 1969 Programming languages provide the abstractions, organizing principles, and control structures that programmers use to write good programs This book is about the concepts that appear in programming languages, issues that arise in their implementation, and the way that language design affects program development The text is divided into four parts: Part 1: Functions and Foundations Part 2: Procedures, Types, Memory Management, and Control Part 3: Modularity, Abstraction, and Object-Oriented Programming Part 4: Concurrency and Logic Programming Part contains a short study of Lisp as a worked example of programming language analysis and covers compiler structure, parsing, lambda calculus, and denotational semantics A short Computability chapter provides information about the limits of compile-time program analysis and optimization Part uses procedural Algol family languages and ML to study types, memory management, and control structures In Part we look at program organization using abstract data types, modules, and objects Because object-oriented programming is the most prominent paradigm in current practice, several different object-oriented languages are compared Separate chapters explore and compare Simula, Smalltalk, C++, and Java Part contains chapters on language mechanisms for concurrency and on logic programming The book is intended for upper-level undergraduate students and beginning graduate students with some knowledge of basic programming Students are expected to have some knowledge of C or some other procedural language and some acquaintance with C++ or some form of object-oriented language Some experience with Lisp, Scheme, or ML is helpful in Parts and 2, although many students have successfully completed the course based on this book without this background It is also helpful if students have some experience with simple analysis of algorithms and data structures For example, in comparing implementations of certain constructs, it will be useful to distinguish between algorithms of constant-, polynomial-, and exponential-time complexity After reading this book, students will have a better understanding of the range of programming languages that have been used over the past 40 years, a better understanding of the issues and trade-offs that arise in programming language design, and a better appreciation of the advantages and pitfalls of the programming languages they use Because different languages present different programming concepts, students will be able to improve their programming by importing ideas from other languages into the programs they write Acknowledgments This book developed as a set of notes for Stanford CS 242, a course in programming languages that I have taught since 1993 Each year, energetic teaching assistants have helped debug example programs for lectures, formulate homework problems, and prepare model solutions The organization and content of the course have been improved greatly by their suggestions Special thanks go to Kathleen Fisher, who was a teaching assistant in 1993 and 1994 and taught the course in my absence in 1995 Kathleen helped me organize the material in the early years and, in 1995, transcribed my handwritten notes into online form Thanks to Amit Patel for his initiative in organizing homework assignments and solutions and to Vitaly Shmatikov for persevering with the glossary of programming language terms Anne Bracy, Dan Bentley, and Stephen Freund thoughtfully proofread many chapters Lauren Cowles, Alan Harvey, and David Tranah of Cambridge University Press were encouraging and helpful I particularly appreciate Lauren's careful reading and detailed comments of twelve full chapters in draft form Thanks also are due to the reviewers they enlisted, who made a number of helpful suggestions on early versions of the book Zena Ariola taught from book drafts at the University of Oregon several years in a row and sent many helpful suggestions; other test instructors also provided helpful feedback Finally, special thanks to Krzystof Apt for contributing a chapter on logic programming John Mitchell Team-Fly Team-Fly Part 1: Function and Foundations Chapter 1: Introduction Chapter 2: Computability Chapter 3: Lisp- Functions, Recursion, and Lists Chapter 4: Fundamentals Team-Fly Team-Fly Chapter 1: Introduction "The Medium Is the Message" Marshall McLuhan 1.1 PROGRAMMING LANGUAGES Programming languages are the medium of expression in the art of computer programming An ideal programming language will make it easy for programmers to write programs succinctly and clearly Because programs are meant to be understood, modified, and maintained over their lifetime, a good programming language will help others read programs and understand how they work Software design and construction are complex tasks Many software systems consist of interacting parts These parts, or software components, may interact in complicated ways To manage complexity, the interfaces and communication between components must be designed carefully A good language for large-scale programming will help programmers manage the interaction among software components effectively In evaluating programming languages, we must consider the tasks of designing, implementing, testing, and maintaining software, asking how well each language supports each part of the software life cycle There are many difficult trade-offs in programming language design Some language features make it easy for us to write programs quickly, but may make it harder for us to design testing tools or methods Some language constructs make it easier for a compiler to optimize programs, but may make programming cumbersome Because different computing environments and applications require different program characteristics, different programming language designers have chosen different trade-offs In fact, virtually all successful programming languages were originally designed for one specific use This is not to say that each language is good for only one purpose However, focusing on a single application helps language designers make consistent, purposeful decisions A single application also helps with one of the most difficult parts of language design: leaving good ideas out I hope you enjoy using this book At the beginning of each chapter, I have included pictures of people involved in the development or analysis of programming languages Some of these people are famous, with major awards and published biographies Others are less widely recognized When possible, I have tried to include some personal information based on my encounters with these people This is to emphasize that programming languages are developed by real human beings Like most human artifacts, a programming language inevitably reflects some of the personality of its designers As a disclaimer, let me point out that I have not made an attempt to be comprehensive in my brief biographical comments I have tried to liven up the text with a bit of humor when possible, leaving serious biography to more serious biographers There simply is not space to mention all of the people who have played important roles in the history of programming languages Historical and biographical texts on computer science and computer scientists have become increasingly available in recent years If you like reading about computer pioneers, you might enjoy paging through Out of Their Minds: The Lives and Discoveries of 15 Great Computer Scientists by Dennis Shasha and Cathy Lazere or other books on the history of computer science John Mitchell Even if you not use many of the programming languages in this book, you may still be able to put the conceptual framework presented in these languages to good use When I was a student in the mid-1970s, all "serious" programmers (at my university, anyway) used Fortran Fortran did not allow recursion, and recursion was generally regarded as too inefficient to be practical for "real programming." However, the instructor of one course I took argued that recursion was still an important idea and explained how recursive techniques could be used in Fortran by managing data in an array I am glad I took that course and not one that dismissed recursion as an impractical idea In the 1980s, many people considered object-oriented programming too inefficient and clumsy for real programming However, students who learned about object-oriented programming in the 1980s were certainly happy to know about these "futuristic" languages in the 1990s, as object-oriented programming became more widely accepted and used Although this is not a book about the history of programming languages, there is some attention to history throughout the book One reason for discussing historical languages is that this gives us a realistic way to understand programming language trade-offs For example, programs were different when machines were slow and memory was scarce The concerns of programming language designers were therefore different in the 1960s from the current concerns By imaging the state of the art in some bygone era, we can give more serious thought to why language designers made certain decisions This way of thinking about languages and computing may help us in the future, when computing conditions may change to resemble some past situation For example, the recent rise in popularity of handheld computing devices and embedded processors has led to renewed interest in programming for devices with limited memory and limited computing power When we discuss specific languages in this book, we generally refer to the original or historically important form of a language For example, "Fortran" means the Fortran of the 1960s and early 1970s These early languages were called Fortran I, Fortran II, Fortran III, and so on In recent years, Fortran has evolved to include more modern features, and the distinction between Fortran and other languages has blurred to some extent Similarly, Lisp generally refers to the Lisps of the 1960s, Smalltalk to the language of the late 1970s and 1980s, and so on Team-Fly Team-Fly 1.2 GOALS In this book we are concerned with the basic concepts that appear in modern programming languages, their interaction, and the relationship between programming languages and methods for program development A recurring theme is the trade-off between language expressiveness and simplicity of implementation For each programming language feature we consider, we examine the ways that it can be used in programming and the kinds of implementation techniques that may be used to compile and execute it efficiently 1.2.1 General Goals In this book we have the following general goals: To understand the design space of programming languages This includes concepts and constructs from past programming languages as well as those that may be used more widely in the future We also try to understand some of the major conflicts and trade-offs between language features, including implementation costs To develop a better understanding of the languages we currently use by comparing them with other languages To understand the programming techniques associated with various language features The study of programming languages is, in part, the study of conceptual frameworks for problem solving, software construction, and development Many of the ideas in this book are common knowledge among professional programmers The material and ways of thinking presented in this book should be useful to you in future programming and in talking to experienced programmers if you work for a software company or have an interview for a job By the end of the course, you will be able to evaluate language features, their costs, and how they fit together 1.2.2 Specific Themes Here are some specific themes that are addressed repeatedly in the text: Computability: Some problems cannot be solved by computer The undecidability of the halting problem implies that programming language compilers and interpreters cannot everything that we might wish they could Static analysis: There is a difference between compile time and run time At compile time, the program is known but the input is not At run time, the program and the input are both available to the run-time system Although a program designer or implementer would like to find errors at compile time, many will not surface until run time Methods that detect program errors at compile time are usually conservative, which means that when they say a program does not have a certain kind of error this statement is correct However, compile-time error-detection methods will usually say that some programs contain errors even if errors may not actually occur when the program is run Expressiveness versus efficiency: There are many situations in which it would be convenient to have a programming language implementation something automatically An example discussed in Chapter is memory management: The Lisp run-time system uses garbage collection to detect memory locations no longer needed by the program When something is done automatically, there is a cost Although an automatic method may save the programmer from thinking about something, the implementation of the language may run more slowly In some cases, the automatic method may make it easier to write programs and make programming less prone to error In other cases, the Team-Fly Index N name clash in multiple inheritance, 362 name type equality, 153 natural language, 76 nondeterministic program, 434 nonterminal, 52 normal form, 66 Nygaard, Kristen, 301 Team-Fly Team-Fly Index O O'Keefe, R.A., 507 object, 265, 277, 303, 312, 344 Object (class in Java), 394, 418 object-oriented, 277 object-oriented programming class, 278 operand stack, 407 operational semantics, 68 operator, 492 overloading, 150, 281, 342, 390 resolution, 151 override (in inheritance), 316, 393, 394 Team-Fly Team-Fly Index P package in Java, 392 parameter passing, 388 parametric polymorphism, 145, 146, 150, 401 parent thread, 445 parse tree, 51, 54 parsing, 51, 55 partial function, 12 partial recursive function, 14, 21 pass-by-name, 96 pass-by-reference, 174, 342 pass-by-value, 174 pass-by-value/result, 174 P-code, 404 pointer, 306 pointer arithmetic, 133, 407 polymorphism, 141, 145 ad hoc, 145 parametric, 145 subtype, 145 precedence in parsing, 56 prefix form, 492 prescient store, 463 priority, 492 priority queue, 240 private, 286 private base class in C++, 348 private member in C++, 347 private methods, 304 procedural abstraction, 242 procedural interpretation, 477 procedure, 170 process, 433 process communication, 435 program component, 239 program analysis, 74 Dylan, 279 propositional symbol, 483 protected, 286 protected member in C++, 347 protection domain, 415 prototyping, 239 public, 286 public base class in C++, 348 public member in C++, 347 public methods, 304 pure Lisp, 23 Python, 362 Team-Fly Team-Fly Index Q query, 483 Team-Fly Team-Fly Index R raise exception, 207 range of a function, 12 reduction, 65 reentrant locking, 457 ref in Simula, 306 reference cell, 118 reference implementation, 164 reference type, 396 referential transparency, 78 relation symbol, 483 remote interface, 465 representation independence, 248, 249, 270 resolution of overloading, 151 R-value, 118 Roussel, Ph., 476 rule in Prolog, 485 Team-Fly Team-Fly Index S sandbox, 412, 414, 419 scope, 25, 59 dynamic, 176 of declaration, 167 of binding, 59 resolution operator, 344 static, 176 second-order function, 35 security, 412 selector, 312 Self, 279 semantic analysis, 51 semantics, 48 semaphore, 440 Shapiro, E., 507 side effect, 23, 39 signal, 438 signature in SML, 255 simple clause, 483 simple logic program, 483 single dispatch, 281 source language, 50 special forms, 24 specification, 239, 269 stack frame, 165 start symbol (of grammar), 53 state, 67 statement, 26 static field, 390 static link, 178 static methods, 390 static scope, 25, 176 Sterling, L., 507 Steele, Guy, 205 STL iterators, 267 range, 267 strictness, 27 strong typing, 121 Stroustrup, Bjarne, 338 structural type equality, 153 structure in SML, 255 stub for remote object, 465 subclass, 308, 312, 344, 392, 418 substitutivity, 284 subtype polymorphism, 145, 401 subtyping, 278, 284, 293, 309 super, 393 superclass, 308, 344, 392, 418 synchronized object, 441 synchronous communication, 435, 467 syntactic sugar, 61 syntax, 48 Team-Fly Team-Fly Index T tail call, 180 tail recursion, 180 tail recursive, 180 target language, 50 task, 433 terminal, 53 test-and-set, 439 thread, 433, 445 throw exception, 207, 398 token, 50 transparent type, 244 true in Lisp, 24 try-finally in Java, 399 Turing complete, 14 Turing machine, 14 type, 129 casts, 133 checking, 135 confusion, 416 constructors, 121 declaration opaque, 254 transparent, 254 error, 130, 309 inference, 135 safety, 387, 416 variables, 135 Team-Fly Team-Fly Index U unbuffered communication, 467 unbuffered message passing, 435 undecidable, 134 unification problem, 481 uniform data representation, 149 upcall, 183, 218 Team-Fly Team-Fly Index V variable anonymous, 486 verification, 406 virtual, 281 base classes, 365 function in C++, 343, 347, 349, 366 table (vtable), 349 machine (VM), 404 von Neumann bottleneck, 81 vtable, 349 vtbl, 349 Team-Fly Team-Fly Index W wait, 438 Warren, D.H, 476 Team-Fly Team-Fly List of Figures Chapter 7: Scope, Functions, and Storage Management Figure 7.1: Program stack Figure 7.2: Stack grows and shrinks during program execution Figure 7.3: Activation records with control links Figure 7.4: Activation record associated with function call Figure 7.5: Activation record with access link for functions call with static scope Figure 7.6: Run-time stack after call to g inside f Figure 7.7: Three calls to tail recursive tlfact without optimization Figure 7.8: Three calls to tail recursive tlfact with optimization Figure 7.9: Access link set from clouser Figure 7.10: Activation records for function closure returned from function Chapter 11: History of Objects-Simula and Smalltalk Figure 11.1: Points, circles, and their lines of intersection Figure 11.2: Definition of Point class Figure 11.3: Run-time representation of Point object and class Figure 11.4: Definition of ColoredPoint class Figure 11.5: Run-time representation of ColoredPoint object and class Figure 11.6: Smalltalk collection class hierarchy Figure P.11.4.1: Smalltalk run-time structures for Point and PolarPoint Chapter 12: Objects and Run-Time Efficiency- C++ Figure 12.1: Representation of Point and ColoredPoint in C++ Figure 12.2: Multiple inheritance Figure 12.3: Object and vtable layout for multiple inheritance Figure 12.4: Diamond inheritance Figure 12.5: Virtual base class Chapter 13: Portability and Safety-Java Figure 13.1: Java package and class visibility Figure 13.2: Classification of types in Java Figure 13.3: Java exception classes Figure 13.4: JVM Figure 13.5: Optimizing invokevirtual by rewriting bytecode Figure 13.6: Optimizing invokeinterface by rewriting bytecode Chapter 14: Concurrent and Distributed Programming Figure 14.1: Messages and state change for a finite-set actor Chapter 15: The Logic Programming Paradigm and Prolog Figure 15.1: Xs is a sublist of the list Ys Team-Fly Team-Fly List of Tables Chapter 13: Portability and Safety-Java Table 13.1: Java design decisions Chapter 15: The Logic Programming Paradigm and Prolog Table 15.1 Team-Fly ... Advanced topics include concurrency and concurrent object-oriented programming A chapter on logic programming illustrates the importance of specialized programming methods for certain kinds of... semantics, in an easy-to-read, informal style, focusing on the main insights provided by these theories Advanced topics include concurrency and concurrent object-oriented programming A chapter... the 1990s brought increasing interest in network-centric computing, interoperability, and security and st correctness issues associated with active content on the Internet The 21 century promises