
- •New to the Tenth Edition
- •Preface
- •Acknowledgments
- •About the Author
- •Contents
- •1.1 Reasons for Studying Concepts of Programming Languages
- •1.2 Programming Domains
- •1.3 Language Evaluation Criteria
- •1.4 Influences on Language Design
- •1.5 Language Categories
- •1.6 Language Design Trade-Offs
- •1.7 Implementation Methods
- •1.8 Programming Environments
- •Summary
- •Problem Set
- •2.1 Zuse’s Plankalkül
- •2.2 Pseudocodes
- •2.3 The IBM 704 and Fortran
- •2.4 Functional Programming: LISP
- •2.5 The First Step Toward Sophistication: ALGOL 60
- •2.6 Computerizing Business Records: COBOL
- •2.7 The Beginnings of Timesharing: BASIC
- •2.8 Everything for Everybody: PL/I
- •2.9 Two Early Dynamic Languages: APL and SNOBOL
- •2.10 The Beginnings of Data Abstraction: SIMULA 67
- •2.11 Orthogonal Design: ALGOL 68
- •2.12 Some Early Descendants of the ALGOLs
- •2.13 Programming Based on Logic: Prolog
- •2.14 History’s Largest Design Effort: Ada
- •2.15 Object-Oriented Programming: Smalltalk
- •2.16 Combining Imperative and Object-Oriented Features: C++
- •2.17 An Imperative-Based Object-Oriented Language: Java
- •2.18 Scripting Languages
- •2.19 The Flagship .NET Language: C#
- •2.20 Markup/Programming Hybrid Languages
- •Review Questions
- •Problem Set
- •Programming Exercises
- •3.1 Introduction
- •3.2 The General Problem of Describing Syntax
- •3.3 Formal Methods of Describing Syntax
- •3.4 Attribute Grammars
- •3.5 Describing the Meanings of Programs: Dynamic Semantics
- •Bibliographic Notes
- •Problem Set
- •4.1 Introduction
- •4.2 Lexical Analysis
- •4.3 The Parsing Problem
- •4.4 Recursive-Descent Parsing
- •4.5 Bottom-Up Parsing
- •Summary
- •Review Questions
- •Programming Exercises
- •5.1 Introduction
- •5.2 Names
- •5.3 Variables
- •5.4 The Concept of Binding
- •5.5 Scope
- •5.6 Scope and Lifetime
- •5.7 Referencing Environments
- •5.8 Named Constants
- •Review Questions
- •6.1 Introduction
- •6.2 Primitive Data Types
- •6.3 Character String Types
- •6.4 User-Defined Ordinal Types
- •6.5 Array Types
- •6.6 Associative Arrays
- •6.7 Record Types
- •6.8 Tuple Types
- •6.9 List Types
- •6.10 Union Types
- •6.11 Pointer and Reference Types
- •6.12 Type Checking
- •6.13 Strong Typing
- •6.14 Type Equivalence
- •6.15 Theory and Data Types
- •Bibliographic Notes
- •Programming Exercises
- •7.1 Introduction
- •7.2 Arithmetic Expressions
- •7.3 Overloaded Operators
- •7.4 Type Conversions
- •7.5 Relational and Boolean Expressions
- •7.6 Short-Circuit Evaluation
- •7.7 Assignment Statements
- •7.8 Mixed-Mode Assignment
- •Summary
- •Problem Set
- •Programming Exercises
- •8.1 Introduction
- •8.2 Selection Statements
- •8.3 Iterative Statements
- •8.4 Unconditional Branching
- •8.5 Guarded Commands
- •8.6 Conclusions
- •Programming Exercises
- •9.1 Introduction
- •9.2 Fundamentals of Subprograms
- •9.3 Design Issues for Subprograms
- •9.4 Local Referencing Environments
- •9.5 Parameter-Passing Methods
- •9.6 Parameters That Are Subprograms
- •9.7 Calling Subprograms Indirectly
- •9.8 Overloaded Subprograms
- •9.9 Generic Subprograms
- •9.10 Design Issues for Functions
- •9.11 User-Defined Overloaded Operators
- •9.12 Closures
- •9.13 Coroutines
- •Summary
- •Programming Exercises
- •10.1 The General Semantics of Calls and Returns
- •10.2 Implementing “Simple” Subprograms
- •10.3 Implementing Subprograms with Stack-Dynamic Local Variables
- •10.4 Nested Subprograms
- •10.5 Blocks
- •10.6 Implementing Dynamic Scoping
- •Problem Set
- •Programming Exercises
- •11.1 The Concept of Abstraction
- •11.2 Introduction to Data Abstraction
- •11.3 Design Issues for Abstract Data Types
- •11.4 Language Examples
- •11.5 Parameterized Abstract Data Types
- •11.6 Encapsulation Constructs
- •11.7 Naming Encapsulations
- •Summary
- •Review Questions
- •Programming Exercises
- •12.1 Introduction
- •12.2 Object-Oriented Programming
- •12.3 Design Issues for Object-Oriented Languages
- •12.4 Support for Object-Oriented Programming in Smalltalk
- •12.5 Support for Object-Oriented Programming in C++
- •12.6 Support for Object-Oriented Programming in Objective-C
- •12.7 Support for Object-Oriented Programming in Java
- •12.8 Support for Object-Oriented Programming in C#
- •12.9 Support for Object-Oriented Programming in Ada 95
- •12.10 Support for Object-Oriented Programming in Ruby
- •12.11 Implementation of Object-Oriented Constructs
- •Summary
- •Programming Exercises
- •13.1 Introduction
- •13.2 Introduction to Subprogram-Level Concurrency
- •13.3 Semaphores
- •13.4 Monitors
- •13.5 Message Passing
- •13.6 Ada Support for Concurrency
- •13.7 Java Threads
- •13.8 C# Threads
- •13.9 Concurrency in Functional Languages
- •13.10 Statement-Level Concurrency
- •Summary
- •Review Questions
- •Problem Set
- •14.1 Introduction to Exception Handling
- •14.2 Exception Handling in Ada
- •14.3 Exception Handling in C++
- •14.4 Exception Handling in Java
- •14.5 Introduction to Event Handling
- •14.6 Event Handling with Java
- •14.7 Event Handling in C#
- •Review Questions
- •Problem Set
- •15.1 Introduction
- •15.2 Mathematical Functions
- •15.3 Fundamentals of Functional Programming Languages
- •15.4 The First Functional Programming Language: LISP
- •15.5 An Introduction to Scheme
- •15.6 Common LISP
- •15.8 Haskell
- •15.10 Support for Functional Programming in Primarily Imperative Languages
- •15.11 A Comparison of Functional and Imperative Languages
- •Review Questions
- •Problem Set
- •16.1 Introduction
- •16.2 A Brief Introduction to Predicate Calculus
- •16.3 Predicate Calculus and Proving Theorems
- •16.4 An Overview of Logic Programming
- •16.5 The Origins of Prolog
- •16.6 The Basic Elements of Prolog
- •16.7 Deficiencies of Prolog
- •16.8 Applications of Logic Programming
- •Review Questions
- •Programming Exercises
- •Bibliography
- •Index

Summary 341
names are bound to values with the val declaration, whose form is exemplified in the following:
val cost = quantity * price;
If cost appears on the left side of a subsequent val declaration, that declaration creates a new version of the name cost, which has no relationship with the previous version, which is then hidden.
F# has a somewhat similar declaration that uses the let reserved word. The difference between F#’s let and ML’s val is that let creates a new scope, whereas val does not. In fact, val declarations are often nested in let constructs in ML. Both let and val are further discussed in Chapter 15.
7.8 Mixed-Mode Assignment
Mixed-mode expressions were discussed in Section 7.4.1. Frequently, assignment statements also are mixed mode. The design question is: Does the type of the expression have to be the same as the type of the variable being assigned, or can coercion be used in some cases of type mismatch?
Fortran, C, C++, and Perl use coercion rules for mixed-mode assignment that are similar to those they use for mixed-mode expressions; that is, many of the possible type mixes are legal, with coercion freely applied.7 Ada does not allow mixed-mode assignment.
In a clear departure from C++, Java and C# allow mixed-mode assignment only if the required coercion is widening.8 So, an int value can be assigned to a float variable, but not vice versa. Disallowing half of the possible mixedmode assignments is a simple but effective way to increase the reliability of Java and C#, relative to C and C++.
Of course, in functional languages, where assignments are just used to name values, there is no such thing as a mixed-mode assignment.
S U M M A R Y
Expressions consist of constants, variables, parentheses, function calls, and operators. Assignment statements include target variables, assignment operators, and expressions.
7.Note that in Python and Ruby, types are associated with objects, not variables, so there is no such thing as mixed-mode assignment in those languages.
8.Not quite true: If an integer literal, which the compiler by default assigns the type int, is assigned to a char, byte, or short variable and the literal is in the range of the type of the variable, the int value is coerced to the type of the variable in a narrowing conversion. This narrowing conversion cannot result in an error.

342 |
Chapter 7 Expressions and Assignment Statements |
The semantics of an expression is determined in large part by the order of evaluation of operators. The associativity and precedence rules for operators in the expressions of a language determine the order of operator evaluation in those expressions. Operand evaluation order is important if functional side effects are possible. Type conversions can be widening or narrowing. Some narrowing conversions produce erroneous values. Implicit type conversions, or coercions, in expressions are common, although they eliminate the errordetection benefit of type checking, thus lowering reliability.
Assignment statements have appeared in a wide variety of forms, including conditional targets, assigning operators, and list assignments.
R E V I E W Q U E S T I O N S
1.Define operator precedence and operator associativity.
2.What is a ternary operator?
3.What is a prefix operator?
4.What operator usually has right associativity?
5.What is a nonassociative operator?
6.What associativity rules are used by APL?
7.What is the difference between the way operators are implemented in C++ and Ruby?
8.Define functional side effect.
9.What is a coercion?
10.What is a conditional expression?
11.What is an overloaded operator?
12.Define narrowing and widening conversions.
13.In JavaScript, what is the difference between == and ===?
14.What is a mixed-mode expression?
15.What is referential transparency?
16.What are the advantages of referential transparency?
17.How does operand evaluation order interact with functional side effects?
18.What is short-circuit evaluation?
19.Name a language that always does short-circuit evaluation of Boolean expressions. Name one that never does it. Name one in which the programmer is allowed to choose.
20.How does C support relational and Boolean expressions?
21.What is the purpose of a compound assignment operator?
22.What is the associativity of C’s unary arithmetic operators?

Problem Set |
343 |
23.What is one possible disadvantage of treating the assignment operator as if it were an arithmetic operator?
24.What two languages include multiple assignments?
25.What mixed-mode assignments are allowed in Ada?
26.What mixed-mode assignments are allowed in Java?
27.What mixed-mode assignments are allowed in ML?
28.What is a cast?
P R O B L E M S E T
1.When might you want the compiler to ignore type differences in an expression?
2.State your own arguments for and against allowing mixed-mode arithmetic expressions.
3.Do you think the elimination of overloaded operators in your favorite language would be beneficial? Why or why not?
4.Would it be a good idea to eliminate all operator precedence rules and require parentheses to show the desired precedence in expressions? Why or why not?
5.Should C’s assigning operations (for example, +=) be included in other languages (that do not already have them)? Why or why not?
6.Should C’s single-operand assignment forms (for example, ++count) be included in other languages (that do not already have them)? Why or why not?
7.Describe a situation in which the add operator in a programming language would not be commutative.
8.Describe a situation in which the add operator in a programming language would not be associative.
9.Assume the following rules of associativity and precedence for expressions:
Precedence |
Highest |
*, /, not |
|
|
+, –, &, mod |
|
|
– (unary) |
|
|
=, /=, < , <=, >=, > |
|
|
and |
|
Lowest |
or, xor |
Associativity |
Left to right |

344 |
Chapter 7 Expressions and Assignment Statements |
Show the order of evaluation of the following expressions by parenthesizing all subexpressions and placing a superscript on the right parenthesis to indicate order. For example, for the expression
a + b * c + d
the order of evaluation would be represented as
((a + (b * c)1)2 + d)3
a.a * b - 1 + c
b.a * (b - 1) / c mod d
c.(a - b) / c & (d * e / a - 3)
d.-a or c = d and e
e.a > b xor c or d <= 17
f.-a + b
10.Show the order of evaluation of the expressions of Problem 9, assuming that there are no precedence rules and all operators associate right to left.
11.Write a BNF description of the precedence and associativity rules defined for the expressions in Problem 9. Assume the only operands are the names a,b,c,d, and e.
12.Using the grammar of Problem 11, draw parse trees for the expressions of Problem 9.
13.Let the function fun be defined as
int fun(int *k) { *k += 4;
return 3 * (*k) - 1;
}
Suppose fun is used in a program as follows:
void main() {
int i = 10, j = 10, sum1, sum2; sum1 = (i / 2) + fun(&i);
sum2 = fun(&j) + (j / 2);
}
What are the values of sum1 and sum2
a.if the operands in the expressions are evaluated left to right?
b.if the operands in the expressions are evaluated right to left?