Tải bản đầy đủ (.pdf) (532 trang)

Ebook Programing language pragmatics (3rd edition) Part 1

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (4.65 MB, 532 trang )


In Praise of Programming Language Pragmatics,Third Edition
The ubiquity of computers in everyday life in the 21st century justifies the centrality of programming languages to computer science education. Programming languages is the area that connects the
theoretical foundations of computer science, the source of problem-solving algorithms, to modern
computer architectures on which the corresponding programs produce solutions. Given the speed
with which computing technology advances in this post-Internet era, a computing textbook must
present a structure for organizing information about a subject, not just the facts of the subject itself.
In this book, Michael Scott broadly and comprehensively presents the key concepts of programming
languages and their implementation, in a manner appropriate for computer science majors.
— From the Foreword by Barbara Ryder, Virginia Tech
Programming Language Pragmatics is an outstanding introduction to language design and implementation. It illustrates not only the theoretical underpinnings of the languages that we use, but also the
ways in which they have been guided by the development of computer architecture, and the ways in
which they continue to evolve to meet the challenge of exploiting multicore hardware.
— Tim Harris, Microsoft Research
Michael Scott has provided us with a book that is faithful to its title—Programming Language Pragmatics. In addition to coverage of traditional language topics, this text delves into the sometimes
obscure, but always necessary, details of fielding programming artifacts. This new edition is current
in its coverage of modern language fundamentals, and now includes new and updated material on
modern run-time environments, including virtual machines. This book is an excellent introduction
for anyone wishing to develop languages for real-world applications.
— Perry Alexander, Kansas University
Michael Scott has improved this new edition of Programming Language Pragmatic in big and small
ways. Changes include the addition of even more insightful examples, the conversion of Pascal
and MIPS examples to C and Intel 86, as well as a completely new chapter on run-time systems.
The additional chapter provides a deeper appreciation of the design and implementation issues of
modern languages.
— Eileen Head, Binghamton University
This new edition brings the gold standard of this dynamic field up to date while maintaining an
excellent balance of the three critical qualities needed in a textbook: breadth, depth, and clarity.
— Christopher Vickery, Queens College of CUNY
Programming Language Pragmatics provides a comprehensive treatment of programming language
theory and implementation. Michael Scott explains the concepts well and illustrates the practical


implications with hundreds of examples from the most popular and influential programming languages. With the welcome addition of a chapter on run-time systems, the third edition includes new
topics such as virtual machines, just-in-time compilation and symbolic debugging.
— William Calhoun, Bloomsburg University


This page intentionally left blank


Programming Language Pragmatics
THIRD EDITION


About the Author
Michael L. Scott is a professor and past chair of the Department of Computer Science at the University of Rochester. He received his Ph.D. in computer sciences in
1985 from the University of Wisconsin–Madison. His research interests lie at the
intersection of programming languages, operating systems, and high-level computer architecture, with an emphasis on parallel and distributed computing. He
is the designer of the Lynx distributed programming language and a co-designer
of the Charlotte and Psyche parallel operating systems, the Bridge parallel file
system, the Cashmere and InterWeave shared memory systems, and the RSTM
suite of transactional memory implementations. His MCS mutual exclusion lock,
co-designed with John Mellor-Crummey, is used in a variety of commercial and
academic systems. Several other algorithms, designed with Maged Michael, Bill
Scherer, and Doug Lea appear in the java.util.concurrent standard library.
In 2006 he and Dr. Mellor-Crummey shared the ACM SIGACT/SIGOPS Edsger
W. Dijkstra Prize in Distributed Computing.
Dr. Scott is a Fellow of the Association for Computing Machinery, a Senior
Member of the Institute of Electrical and Electronics Engineers, and a member
of the Union of Concerned Scientists and Computer Professionals for Social
Responsibility. He has served on a wide variety of program committees and grant
review panels, and has been a principal or co-investigator on grants from the NSF,

ONR, DARPA, NASA, the Departments of Energy and Defense, the Ford Foundation, Digital Equipment Corporation (now HP), Sun Microsystems, IBM, Intel,
and Microsoft. The author of more than 100 refereed publications, he served as
General Chair of the 2003 ACM Symposium on Operating Systems Principles
and as Program Chair of the 2007 ACM SIGPLAN Workshop on Transactional
Computing and the 2008 ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming. In 2001 he received the University of Rochester’s
Robert and Pamela Goergen Award for Distinguished Achievement and Artistry
in Undergraduate Teaching.


Programming Language Pragmatics
TH I R D E D I TI O N

Michael L. Scott
Department of Computer Science
University of Rochester

AMSTERDAM • BOSTON • HEIDELBERG • LONDON
NEW YORK • OXFORD • PARIS • SAN DIEGO
SAN FRANCISCO • SINGAPORE • SYDNEY • TOKYO
Morgan Kaufmann Publishers is an imprint of Elsevier


Morgan Kaufmann Publishers is an imprint of Elsevier
30 Corporate Drive, Suite 400
Burlington, MA 01803
This book is printed on acid-free paper.



Copyright c 2009 by Elsevier Inc. All rights reserved.

Designations used by companies to distinguish their products are often claimed as trade-marks or
registered trademarks. In all instances in which Morgan Kaufmann Publishers is aware of a claim,
the product names appear in initial capital or all capital letters. Readers, however, should contact the
appropriate companies for more complete information regarding trademarks and registration.
No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form
or by any means, electronic, mechanical, photocopying, scanning, or otherwise, without prior written
permission of the publisher.
Permissions may be sought directly from Elsevier’s Science & Technology Rights Department in
Oxford, UK: phone: (+44) 1865 843830, fax: (+44) 1865 853333, e-mail:
You may also complete your request on-line via the Elsevier homepage (), by
selecting “Support & Contact” then “Copyright and Permission” and then “Obtaining Permissions.”
Library of Congress Cataloging-in-Publication Data
Application submitted.
ISBN 13: 978-0-12-374514-9
Cover image: Copyright c 2008, Michael L. Scott.
Beaver Lake, near Lowville, NY, in the foothills of the Adirondacks
For all information on all Morgan Kaufmann publications,
visit our Website at www.books.elsevier.com
Printed in the United States
Transferred to Digital Printing in 2011


To my parents,
Dorothy D. Scott and Peter Lee Scott,
who modeled for their children
the deepest commitment
to humanistic values.


This page intentionally left blank



Contents

Foreword
Preface

I

FOUNDATIONS

1 Introduction
1.1 The Art of Language Design

xxi
xxiii

3
5
7

1.2 The Programming Language Spectrum

10

1.3 Why Study Programming Languages?

14

1.4 Compilation and Interpretation


16

1.5 Programming Environments

24

1.6 An Overview of Compilation
1.6.1 Lexical and Syntax Analysis
1.6.2 Semantic Analysis and Intermediate Code Generation
1.6.3 Target Code Generation
1.6.4 Code Improvement

25
27
29
33
33

1.7 Summary and Concluding Remarks

35

1.8 Exercises

36

1.9 Explorations

37


1.10 Bibliographic Notes

2 Programming Language Syntax
2.1 Specifying Syntax: Regular Expressions and Context-Free Grammars
2.1.1 Tokens and Regular Expressions
2.1.2 Context-Free Grammars
2.1.3 Derivations and Parse Trees

39
41
42
43
46
48


x

Contents

2.2 Scanning
2.2.1 Generating a Finite Automaton
2.2.2 Scanner Code
2.2.3 Table-Driven Scanning
2.2.4 Lexical Errors
2.2.5 Pragmas

51
55

60
63
63
65

2.3 Parsing
2.3.1 Recursive Descent
2.3.2 Table-Driven Top-Down Parsing
2.3.3 Bottom-Up Parsing
2.3.4 Syntax Errors

1

67
70
76
87
99

2.4 Theoretical Foundations
2.4.1 Finite Automata
2.4.2 Push-Down Automata
2.4.3 Grammar and Language Classes

13 · 100
13
18
19

·


2.5 Summary and Concluding Remarks

101

2.6 Exercises

102

2.7 Explorations

108

2.8 Bibliographic Notes

109

3 Names, Scopes, and Bindings

111

3.1 The Notion of Binding Time

112

3.2 Object Lifetime and Storage Management
3.2.1 Static Allocation
3.2.2 Stack-Based Allocation
3.2.3 Heap-Based Allocation
3.2.4 Garbage Collection


114
115
117
118
120

3.3 Scope Rules
3.3.1 Static Scoping
3.3.2 Nested Subroutines
3.3.3 Declaration Order
3.3.4 Modules
3.3.5 Module Types and Classes
3.3.6 Dynamic Scoping

121
123
124
127
132
136
139

3.4 Implementing Scope
3.4.1 Symbol Tables
3.4.2 Association Lists and Central Reference Tables
3.5 The Meaning of Names within a Scope
3.5.1 Aliases

29 · 143

29
33
144
144


xi

Contents

3.5.2 Overloading
3.5.3 Polymorphism and Related Concepts

146
148

3.6 The Binding of Referencing Environments
3.6.1 Subroutine Closures
3.6.2 First-Class Values and Unlimited Extent
3.6.3 Object Closures

151
153
154
157

3.7 Macro Expansion

159


3.8 Separate Compilation
3.8.1 Separate Compilation in C
3.8.2 Packages and Automatic Header Inference
3.8.3 Module Hierarchies

39 · 161
40
42
43

3.9 Summary and Concluding Remarks

162

3.10 Exercises

163

3.11 Explorations

171

3.12 Bibliographic Notes

172

4 Semantic Analysis

175


4.1 The Role of the Semantic Analyzer

176

4.2 Attribute Grammars

180

4.3 Evaluating Attributes

182

4.4 Action Routines

191

4.5 Space Management for Attributes
4.5.1 Bottom-Up Evaluation
4.5.2 Top-Down Evaluation

49 · 196
49
54

4.6 Decorating a Syntax Tree

197

4.7 Summary and Concluding Remarks


204

4.8 Exercises

205

4.9 Explorations

209

4.10 Bibliographic Notes

5 Target Machine Architecture

210
65 · 213

5.1 The Memory Hierarchy

66

5.2 Data Representation
5.2.1 Integer Arithmetic
5.2.2 Floating-Point Arithmetic

68
69
72



xii

Contents

II

5.3 Instruction Set Architecture
5.3.1 Addressing Modes
5.3.2 Conditions and Branches

75
75
76

5.4 Architecture and Implementation
5.4.1 Microprogramming
5.4.2 Microprocessors
5.4.3 RISC
5.4.4 Multithreading and Multicore
5.4.5 Two Example Architectures: The x86 and MIPS

78
79
80
81
82
84

5.5 Compiling for Modern Processors
5.5.1 Keeping the Pipeline Full

5.5.2 Register Allocation

91
91
96

5.6 Summary and Concluding Remarks

101

5.7 Exercises

103

5.8 Explorations

107

5.9 Bibliographic Notes

109

CORE ISSUES IN LANGUAGE DESIGN

6 Control Flow

217
219

6.1 Expression Evaluation

6.1.1 Precedence and Associativity
6.1.2 Assignments
6.1.3 Initialization
6.1.4 Ordering within Expressions
6.1.5 Short-Circuit Evaluation

220
222
224
233
235
238

6.2 Structured and Unstructured Flow
6.2.1 Structured Alternatives to goto
6.2.2 Continuations

241
242
245

6.3 Sequencing

246

6.4 Selection
6.4.1 Short-Circuited Conditions
6.4.2 Case / Switch Statements

247

248
251

6.5 Iteration
6.5.1 Enumeration-Controlled Loops
6.5.2 Combination Loops

256
256
261


Contents

6.5.3 Iterators
6.5.4 Generators in Icon
6.5.5 Logically Controlled Loops
6.6 Recursion
6.6.1 Iteration and Recursion
6.6.2 Applicative- and Normal-Order Evaluation
6.7 Nondeterminacy

xiii

262
111 · 268
268
270
271
275

115 · 277

6.8 Summary and Concluding Remarks

278

6.9 Exercises

279

6.10 Explorations

285

6.11 Bibliographic Notes

287

7 Data Types
7.1 Type Systems
7.1.1 Type Checking
7.1.2 Polymorphism
7.1.3 The Meaning of “Type”
7.1.4 Classification of Types
7.1.5 Orthogonality

289
290
291
291

293
294
301

7.2 Type Checking
7.2.1 Type Equivalence
7.2.2 Type Compatibility
7.2.3 Type Inference
7.2.4 The ML Type System

303
303
310
314
125 · 316

7.3 Records (Structures) and Variants (Unions)
7.3.1 Syntax and Operations
7.3.2 Memory Layout and Its Impact
7.3.3 With Statements
7.3.4 Variant Records (Unions)

317
318
319
135 · 323
139 · 324

7.4 Arrays
7.4.1 Syntax and Operations

7.4.2 Dimensions, Bounds, and Allocation
7.4.3 Memory Layout

325
326
330
335

7.5 Strings

342

7.6 Sets

344

7.7 Pointers and Recursive Types
7.7.1 Syntax and Operations

345
346


xiv

Contents

7.7.2 Dangling References
7.7.3 Garbage Collection
7.8 Lists

7.9 Files and Input/Output
7.9.1 Interactive I/O
7.9.2 File-Based I/O
7.9.3 Text I/O

149 · 356
357
364
153 · 367
153
154
156

7.10 Equality Testing and Assignment

368

7.11 Summary and Concluding Remarks

371

7.12 Exercises

373

7.13 Explorations

379

7.14 Bibliographic Notes


380

8 Subroutines and Control Abstraction
8.1 Review of Stack Layout

383
384

8.2 Calling Sequences
8.2.1 Displays
8.2.2 Case Studies: C on the MIPS; Pascal on the x86
8.2.3 Register Windows
8.2.4 In-Line Expansion

386
·
169
389
173 · 389
181 · 390
391

8.3 Parameter Passing
8.3.1 Parameter Modes
8.3.2 Call-by-Name
8.3.3 Special-Purpose Parameters
8.3.4 Function Returns

393

394
185 · 402
403
408

8.4 Generic Subroutines and Modules
8.4.1 Implementation Options
8.4.2 Generic Parameter Constraints
8.4.3 Implicit Instantiation
8.4.4 Generics in C++, Java, and C#

410
412
414
416
189 · 417

8.5 Exception Handling
8.5.1 Defining Exceptions
8.5.2 Exception Propagation
8.5.3 Implementation of Exceptions

418
421
423
425

8.6 Coroutines
8.6.1 Stack Allocation
8.6.2 Transfer


428
430
432


Contents

8.6.3 Implementation of Iterators
8.6.4 Discrete Event Simulation
8.7 Events
8.7.1 Sequential Handlers
8.7.2 Thread-Based Handlers

xv

201 · 433
205 · 433
434
434
436

8.8 Summary and Concluding Remarks

438

8.9 Exercises

439


8.10 Explorations

446

8.11 Bibliographic Notes

447

9 Data Abstraction and Object Orientation

449

9.1 Object-Oriented Programming

451

9.2 Encapsulation and Inheritance
9.2.1 Modules
9.2.2 Classes
9.2.3 Nesting (Inner Classes)
9.2.4 Type Extensions
9.2.5 Extending without Inheritance

460
460
463
465
466
468


9.3 Initialization and Finalization
9.3.1 Choosing a Constructor
9.3.2 References and Values
9.3.3 Execution Order
9.3.4 Garbage Collection

469
470
472
475
477

9.4 Dynamic Method Binding
9.4.1 Virtual and Nonvirtual Methods
9.4.2 Abstract Classes
9.4.3 Member Lookup
9.4.4 Polymorphism
9.4.5 Object Closures

478
480
482
482
486
489

9.5 Multiple Inheritance
9.5.1 Semantic Ambiguities
9.5.2 Replicated Inheritance
9.5.3 Shared Inheritance

9.5.4 Mix-In Inheritance

215 · 491
217
220
222
223

9.6 Object-Oriented Programming Revisited
9.6.1 The Object Model of Smalltalk

492
·
227
493

9.7 Summary and Concluding Remarks

494


xvi

Contents

9.8 Exercises

495

9.9 Explorations


498

9.10 Bibliographic Notes

III

ALTERNATIVE PROGRAMMING MODELS

10 Functional Languages

499

503
505

10.1 Historical Origins

506

10.2 Functional Programming Concepts

507

10.3 A Review/Overview of Scheme
10.3.1 Bindings
10.3.2 Lists and Numbers
10.3.3 Equality Testing and Searching
10.3.4 Control Flow and Assignment
10.3.5 Programs as Lists

10.3.6 Extended Example: DFA Simulation

509
512
513
514
515
517
519

10.4 Evaluation Order Revisited
10.4.1 Strictness and Lazy Evaluation
10.4.2 I/O: Streams and Monads

521
523
525

10.5 Higher-Order Functions

530

10.6 Theoretical Foundations
10.6.1 Lambda Calculus
10.6.2 Control Flow
10.6.3 Structures

237 · 534
239
242

244

10.7 Functional Programming in Perspective

534

10.8 Summary and Concluding Remarks

537

10.9 Exercises

538

10.10 Explorations

542

10.11 Bibliographic Notes

543

11 Logic Languages

545

11.1 Logic Programming Concepts

546


11.2 Prolog
11.2.1 Resolution and Unification
11.2.2 Lists

547
549
550


Contents

11.2.3
11.2.4
11.2.5
11.2.6
11.2.7

Arithmetic
Search/Execution Order
Extended Example: Tic-Tac-Toe
Imperative Control Flow
Database Manipulation

11.3 Theoretical Foundations
11.3.1 Clausal Form
11.3.2 Limitations
11.3.3 Skolemization

xvii
551

552
554
557
561

253 · 566
254
255
257

11.4 Logic Programming in Perspective
11.4.1 Parts of Logic Not Covered
11.4.2 Execution Order
11.4.3 Negation and the “Closed World” Assumption

566
566
567
568

11.5 Summary and Concluding Remarks

570

11.6 Exercises

571

11.7 Explorations


573

11.8 Bibliographic Notes

573

12 Concurrency

575

12.1 Background and Motivation
12.1.1 The Case for Multithreaded Programs
12.1.2 Multiprocessor Architecture

576
579
581

12.2 Concurrent Programming Fundamentals
12.2.1 Communication and Synchronization
12.2.2 Languages and Libraries
12.2.3 Thread Creation Syntax
12.2.4 Implementation of Threads

586
587
588
589
598


12.3 Implementing Synchronization
12.3.1 Busy-Wait Synchronization
12.3.2 Nonblocking Algorithms
12.3.3 Memory Consistency Models
12.3.4 Scheduler Implementation
12.3.5 Semaphores

603
604
607
610
613
617

12.4 Language-Level Mechanisms
12.4.1 Monitors
12.4.2 Conditional Critical Regions
12.4.3 Synchronization in Java

619
619
624
626


xviii

Contents

12.4.4 Transactional Memory

12.4.5 Implicit Synchronization
12.5 Message Passing
12.5.1 Naming Communication Partners
12.5.2 Sending
12.5.3 Receiving
12.5.4 Remote Procedure Call

629
633
263 · 637
263
267
272
278

12.6 Summary and Concluding Remarks

638

12.7 Exercises

640

12.8 Explorations

645

12.9 Bibliographic Notes

647


13 Scripting Languages

649

13.1 What Is a Scripting Language?
13.1.1 Common Characteristics

650
652

13.2 Problem Domains
13.2.1 Shell (Command) Languages
13.2.2 Text Processing and Report Generation
13.2.3 Mathematics and Statistics
13.2.4 “Glue” Languages and General-Purpose Scripting
13.2.5 Extension Languages

655
655
663
667
668
676

13.3 Scripting the World Wide Web
13.3.1 CGI Scripts
13.3.2 Embedded Server-Side Scripts
13.3.3 Client-Side Scripts
13.3.4 Java Applets

13.3.5 XSLT

680
680
681
686
686
287 · 689

13.4 Innovative Features
13.4.1 Names and Scopes
13.4.2 String and Pattern Manipulation
13.4.3 Data Types
13.4.4 Object Orientation

691
691
696
704
710

13.5 Summary and Concluding Remarks

717

13.6 Exercises

718

13.7 Explorations


723

13.8 Bibliographic Notes

724


Contents

IV

A CLOSER LOOK AT IMPLEMENTATION

14 Building a Runnable Program
14.1 Back-End Compiler Structure
14.1.1 A Plausible Set of Phases
14.1.2 Phases and Passes

xix

727
729
729
730
734

14.2 Intermediate Forms
14.2.1 Diana
14.2.2 The gcc IFs

14.2.3 Stack-Based Intermediate Forms

303 · 734
303
306
736

14.3 Code Generation
14.3.1 An Attribute Grammar Example
14.3.2 Register Allocation

738
738
741

14.4 Address Space Organization

744

14.5 Assembly
14.5.1 Emitting Instructions
14.5.2 Assigning Addresses to Names

746
748
749

14.6 Linking
14.6.1 Relocation and Name Resolution
14.6.2 Type Checking


750
751
751

14.7 Dynamic Linking
14.7.1 Position-Independent Code
14.7.2 Fully Dynamic (Lazy) Linking

311 · 754
312
313

14.8 Summary and Concluding Remarks

755

14.9 Exercises

756

14.10 Explorations

758

14.11 Bibliographic Notes

759

15 Run-time Program Management


761

15.1 Virtual Machines
15.1.1 The Java Virtual Machine
15.1.2 The Common Language Infrastructure

764
766
775

15.2 Late Binding of Machine Code
15.2.1 Just-in-Time and Dynamic Compilation
15.2.2 Binary Translation

784
785
791


xx

Contents

15.2.3 Binary Rewriting
15.2.4 Mobile Code and Sandboxing

795
797


15.3 Inspection/Introspection
15.3.1 Reflection
15.3.2 Symbolic Debugging
15.3.3 Performance Analysis

799
799
806
809

15.4 Summary and Concluding Remarks

811

15.5 Exercises

812

15.6 Explorations

815

15.7 Bibliographic Notes

816

16 Code Improvement

321 · 817


16.1 Phases of Code Improvement

323

16.2 Peephole Optimization

325

16.3 Redundancy Elimination in Basic Blocks
16.3.1 A Running Example
16.3.2 Value Numbering

328
328
331

16.4 Global Redundancy and Data Flow Analysis
16.4.1 SSA Form and Global Value Numbering
16.4.2 Global Common Subexpression Elimination

336
336
339

16.5 Loop Improvement I
16.5.1 Loop Invariants
16.5.2 Induction Variables

346
347

348

16.6 Instruction Scheduling

351

16.7 Loop Improvement II
16.7.1 Loop Unrolling and Software Pipelining
16.7.2 Loop Reordering

355
355
359

16.8 Register Allocation

366

16.9 Summary and Concluding Remarks

370

16.10 Bibliographic Notes

377

A Programming Languages Mentioned

819


B Language Design and Language Implementation

831

C Numbered Examples

835

Bibliography

849

Index

867


Foreword
The ubiquity of computers in everyday life in the 21st century justifies the centrality of programming languages to computer science education. Programming
languages is the area that connects the theoretical foundations of computer science,
the source of problem-solving algorithms, to modern computer architectures on
which the corresponding programs produce solutions. Given the speed with which
computing technology advances in this post-Internet era, a computing textbook
must present a structure for organizing information about a subject, not just the
facts of the subject itself. In this book, Michael Scott broadly and comprehensively
presents the key concepts of programming languages and their implementation,
in a manner appropriate for computer science majors.
The key strength of Scott’s book is that he holistically combines descriptions of
language concepts with concrete explanations of how to realize them. The depth of
these discussions, which have been updated in this third edition to reflect current

research and practice, provide basic information as well as supplemental material
for the reader interested in a specific topic. By eliding some topics selectively,
the instructor can still create a coherent exploration of a subset of the subject
matter. Moreover, Scott uses numerous examples from real languages to illustrate
key points. For interested or motivated readers, additional in-depth and advanced
discussions and exercises are available on the book’s companion CD, enabling
students with a range of interests and abilities to further explore on their own the
fundamentals of programming languages and compilation.
I have taught a semester-long comparative programming languages course
using Scott’s book for the last several years. I emphasize to students that my
goal is for them to learn how to learn a programming language, rather than to
retain detailed specifics of any one programming language. The purpose of the
course is to teach students an organizational framework for learning new languages throughout their careers, a certainty in the computer science field. To this
end, I particularly like Scott’s chapters on programming language paradigms (i.e.,
functional, logic, object-oriented, scripting), and my course material is organized
in this manner. However, I also have included foundational topics such as memory
organization, names and locations, scoping, types, and garbage collection–all of
which benefit from being presented in a manner that links the language concept
to its implementation details. Scott’s explanations are to the point and intuitive,
with clear illustrations and good examples. Often, discussions are independent
of previously presented material, making it easier to pick and choose topics for

xxi


xxii

Foreword

the syllabus. In addition, many supplemental teaching materials are provided on

the Web.
Of key interest to me in this new edition are the new Chapter 15 on run-time
environments and virtual machines (VMs), and the major update of Chapter
12 on concurrency. Given the current emphasis on virtualization, including a
chapter on VMs, such as Java’s JVM and CLI, facilitates student understanding
of this important topic and explains how modern languages achieve portability
over many platforms. The discussion of dynamic compilation and binary translation provides a contrast to the more traditional model of compilation presented
earlier in the book. It is important that Scott includes this newer compilation
technology so that a student can better understand what is needed to support the
newer dynamic language features described. Further, the discussions of symbolic
debugging and performance analysis demonstrate that programming language
and compiler technology pervade the software development cycle.
Similarly, Chapter 12 has been augmented with discussions of newer topics
that have been the focus of recent research (e.g., memory consistency models,
software transactional memory). A discussion of concurrency as a programming
paradigm belongs in a programming languages course, not just in an operating
systems course. In this context, language design choices easily can be compared
and contrasted, and their required implementations considered. This blurring
of the boundaries between language design, compilation, operating systems, and
architecture characterizes current software development in practice. This reality
is mirrored in this third edition of Scott’s book.
Besides these major changes, this edition features updated examples (e.g., in
X86 code, in C rather than Pascal) and enhanced discussions in the context of
modern languages such as C#, Java 5, Python, and Eiffel. Presenting examples in
several programming languages helps students understand that it is the underlying
common concepts that are important, not their syntactic differences.
In summary, Michael Scott’s book is an excellent treatment of programming
languages and their implementation. This new third edition provides a good reference for students, to supplement materials presented in lectures. Several coherent
tracks through the textbook allow construction of several “flavors” of courses that
cover much, but not all of the material. The presentation is clear and comprehensive with language design and implementation discussed together and supporting

one another.
Congratulations to Michael on a fine third edition of this wonderful book!
Barbara G. Ryder
J. Byron Maupin Professor of Engineering
Head, Department of Computer Science
Virginia Tech


Preface

A course in computer programming provides the typical student’s first
exposure to the field of computer science. Most students in such a course will
have used computers all their lives, for email, games, web browsing, word processing, social networking, and a host of other tasks, but it is not until they write their
first programs that they begin to appreciate how applications work. After gaining
a certain level of facility as programmers (presumably with the help of a good
course in data structures and algorithms), the natural next step is to wonder how
programming languages work. This book provides an explanation. It aims, quite
simply, to be the most comprehensive and accurate languages text available, in a
style that is engaging and accessible to the typical undergraduate. This aim reflects
my conviction that students will understand more, and enjoy the material more,
if we explain what is really going on.
In the conventional “systems” curriculum, the material beyond data structures (and possibly computer organization) tends to be compartmentalized into a
host of separate subjects, including programming languages, compiler construction, computer architecture, operating systems, networks, parallel and distributed
computing, database management systems, and possibly software engineering,
object-oriented design, graphics, or user interface systems. One problem with this
compartmentalization is that the list of subjects keeps growing, but the number of
semesters in a Bachelor’s program does not. More important, perhaps, many of the
most interesting discoveries in computer science occur at the boundaries between
subjects. The RISC revolution, for example, forged an alliance between computer architecture and compiler construction that has endured for 25 years. More
recently, renewed interest in virtual machines has blurred the boundaries between

the operating system kernel, the compiler, and the language run-time system.
Programs are now routinely embedded in web pages, spreadsheets, and user interfaces. And with the rise of multicore processors, concurrency issues that used to be
an issue only for systems programmers have begun to impact everyday computing.
Increasingly, both educators and practitioners are recognizing the need to
emphasize these sorts of interactions. Within higher education in particular there
is a growing trend toward integration in the core curriculum. Rather than give the
typical student an in-depth look at two or three narrow subjects, leaving holes in all
the others, many schools have revised the programming languages and computer
organization courses to cover a wider range of topics, with follow-on electives
in various specializations. This trend is very much in keeping with the findings
of the ACM/IEEE-CS Computing Curricula 2001 task force, which emphasize the

xxiii


xxiv

Preface

growth of the field, the increasing need for breadth, the importance of flexibility
in curricular design, and the overriding goal of graduating students who “have
a system-level perspective, appreciate the interplay between theory and practice,
are familiar with common themes, and can adapt over time as the field evolves”
[CR01, Sec. 11.1, adapted].
The first two editions of Programming Language Pragmatics (PLP-1e and -2e)
had the good fortune of riding this curricular trend. This third edition continues
and strengthens the emphasis on integrated learning while retaining a central
focus on programming language design.
At its core, PLP is a book about how programming languages work. Rather than
enumerate the details of many different languages, it focuses on concepts that

underlie all the languages the student is likely to encounter, illustrating those
concepts with a variety of concrete examples, and exploring the tradeoffs that
explain why different languages were designed in different ways. Similarly, rather
than explain how to build a compiler or interpreter (a task few programmers will
undertake in its entirety), PLP focuses on what a compiler does to an input program, and why. Language design and implementation are thus explored together,
with an emphasis on the ways in which they interact.

Changes in the Third Edition
In comparison to the second edition, PLP-3e provides
1.
2.
3.
4.

A new chapter on virtual machines and run-time program management
A major revision of the chapter on concurrency
Numerous other reflections of recent changes in the field
Improvements inspired by instructor feedback or a fresh consideration of
familiar topics

Item 1 in this list is perhaps the most visible change. It reflects the increasingly
ubiquitous use of both managed code and scripting languages. Chapter 15 begins
with a general overview of virtual machines and then takes a detailed look at
the two most widely used examples: the JVM and the CLI. The chapter also
covers dynamic compilation, binary translation, reflection, debuggers, profilers,
and other aspects of the increasingly sophisticated run-time machinery found in
modern language systems.
Item 2 also reflects the evolving nature of the field. With the proliferation
of multicore processors, concurrent languages have become increasingly important to mainstream programmers, and the field is very much in flux. Changes to
Chapter 12 (Concurrency) include new sections on nonblocking synchronization,

memory consistency models, and software transactional memory, as well as
increased coverage of OpenMP, Erlang, Java 5, and Parallel FX for .NET.
Other new material (Item 3) appears throughout the text. Section 5.4.4 covers
the multicore revolution from an architectural perspective. Section 8.7 covers


×