370 likes | 537 Views
Chapter 7 Expressions and Assignment Statements. Peter A. Ng CS 350 Programming Language Design Indiana University – Purdue University Fort Wayne. Chapter 7 Topics. Introduction Arithmetic expressions Overloaded operators Type conversions Relational and Boolean expressions
E N D
Chapter 7Expressions and Assignment Statements Peter A. Ng CS 350 Programming Language Design Indiana University – Purdue University Fort Wayne
Chapter 7 Topics • Introduction • Arithmetic expressions • Overloaded operators • Type conversions • Relational and Boolean expressions • Short-circuit evaluation • Assignment statements • Mixed-mode assignment
Introduction • Expressions are the fundamentalmeansof specifying computations in a programming language. • Arithmetic expressions consist of operators, operands, parentheses, and function calls. • The purpose of an assignment statement is to change the value of a variable. • This is how imperative languages change program state • Arithmetic expressions in programming languages are derived from mathematical notation • Consequently, most binary operators are infix
Infix V.S. Postfix • Infix notation is the most common way we express mathematical calculations to solve equations or expressions • Infix notation: X + Y • Postfix notation is the translation of infix notation separated into fragments for calculation • Postfix notation: X Y +
Translation from infix to postfix: infix = 5*(6-4*2)/5+3 Scan 5 Postfix = 5 Scan * Postfix = 5 PushdownStack = * Scan ( Postfix = 5 PushdownStack = *( Scan 6 Postfix = 5 6 Scan – Postfix = 5 6 PushdownStatck = * ( - Scan 4 Postfix = 5 6 4 Scan * Postfix = 5 6 4 PushdownStack = * ( - * Scan 2 Postfix = 5 6 4 2 Scan ) Pop * Postfix 5 6 4 2 * PushdownStack = * ( - Pop – Postfix 5 6 4 2 * - PushdownStack = * ( Pop ( Postfix 5 6 4 2 * - PushdownStack = * Scan / Pop * Postfix 5 6 4 2 * - * Push / PushdownStack = / Scan 5 Postfix 5 6 4 2 * - * 5 Scan – Pop / Postfix 5 6 4 2 * - * 5 / Push – PushdownStack = - Scan 3 Postfix 5 6 4 2 * - * 5 / 3 Scan NULL Pop – Postfix 5 6 4 2 * - * 5 / 3 - Infix V.S. Postfix • Infix notation is the most common way we express mathematical calculations to solve equations or expressions • Infix notation: X + Y • Postfix notation is the translation of infix notation separated into fragments for calculation • Postfix notation: X Y +
Translation from infix to postfix: infix = 5 * (6 – 4 * 2) / 5 + 3 Scan 5 Postfix = 5 Scan * Postfix = 5 PushdownStack = * Scan ( Postfix = 5 PushdownStack = *( Scan 6 Postfix = 5 6 Scan – Postfix = 5 6 PushdownStatck = * ( - Scan 4 Postfix = 5 6 4 Scan * Postfix = 5 6 4 PushdownStack = * ( - * Scan 2 Scan 5 Postfix 5 6 4 2 * - * 5 Scan – Pop / Postfix 5 6 4 2 * - * 5 / Push – PushdownStack = - Scan 3 Postfix 5 6 4 2 * - * 5 / 3 Scan NULL Pop – Postfix 5 6 4 2 * - * 5 / 3 - Scan 2 Postfix = 5 6 4 2 Scan ) Pop * Postfix 5 6 4 2 * PushdownStack = * ( - Pop – Postfix 5 6 4 2 * - PushdownStack = * ( Pop ( Postfix 5 6 4 2 * - PushdownStack = * Scan / Pop * Postfix 5 6 4 2 * - * Push / PushdownStack = / Scan 5
Design and Implement an algorithm that translates an assignment (in infix form) to an equivalent assignment statement (in postfix form). Remember that the scanner returns token and lexeme to the syntax analyzer. • An example of an assignment is as follows: • x = 5 * (6 – 4 * 2) / 5 + 3; • Design and Implement an algorithm that evaluates an assignment statement which are in postfix form.
Arithmetic expressions • Design issues for arithmetic expressions 1. What are the operator precedence rules? 2. What are the operator associativity rules? 3. What is the order of operand evaluation? 4. Are there restrictions on operand evaluation side effects? 5. Does the language allow user-defined operator overloading? 6. What mode mixing is allowed in expressions?
Arithmetic expressions • To understand expression evaluation, we need to understand the ordersthat operator and operand to be evaluated • Operator evaluation order is governed by • Precedence rules • Associativity rules
Precedence rules • Precedence rules are used to determine which operator should be applied first, if there are two operators with different precedence • The operator with the highest precedence is applied first. • Typical precedence levels (from high to low) 1. Parentheses – () 2. unary operators -- !, ++ 3. *, / 4. +, - • 2 * 3 + 4 = 10 and 2 * (3 + 4) = 24 • 2 + 3 – 8 = 2 + (3 – 8) • 2 + 3 * 4 2 + (3 * 4) (with the result 14) • * has higher precedence than +.
Associativity rules • The operator associativity rules for expression evaluation define the order, in which adjacent operators with the same precedence level are evaluated • Left associativity implies grouping from left to right: • 1 + 2 - 3 is interpreted as ((1 + 2) - 3), since the binary operators + and - both have same precedence and left associativity. • Right associativity implies grouping from right to left: • --4 is interpreted as (- (- 4)) (with the result 4), since the unary operator - has right associativity. • Precedence and associativity rules can be overridden with parentheses
Arithmetic Expressions: Conditional Expressions • Conditional Expressions • C-based languages (e.g., C, C++) • An example: average = (count == 0)? 0 : sum / count • Evaluates as what is written in the following: if (count == 0) average = 0 else average = sum /count
Operand Evaluation Order • Operators can be • Unary – one operand • Binary – two operands • Ternary – three operands • Operand evaluation order makes a difference if operand evaluation causes side effects • Side effects are caused by • Method calls • Unwise use of unary increment or decrement operators
Functional Side Effect For Global Variables • A similar problem exists if global variables are altered • Example • The value of the expression below is . . . b = 8 or 20? One way is b a func(1) + = b 5 3 + = b 8 = b has 8 as value. and a has 17; Another way is b a 3 + = b 17 3 + = b 20 = b and a has 20 and 17. int a = 5; int func1 (){ a = 17; return 3; } void main() { b = a + func1(); }
Functional side effects • Two possible solutions to the problem • Write the language definition to disallow functional side effects • No two-way parameters in functions • No non-local references in functions • Advantage – it works! • Disadvantage – The flexibility of two-way parameters and non-local references losts • Write the language definition to demand that operand evaluationorder to be fixed • Disadvantage – It limits some compiler optimizations • Disadvantage – Requires users to understand more language details
Overloaded operators • Operator overloading is the use of an operator for more than one purpose • Some overloading are confusing • For example, the use of & in C and C++ • bitwise AND andunary “address of” operator • Loss of compiler error detection • r = r1 & r2 would compile fine if r1 were omitted • Some loss of readability • It is better to introduce a new symbol for a totally different operation
Overloaded Operators • Some overloadings are common • For example, the use of + for ints and doubles • Problem: The following C++ code cannot compute the floating-point average correctly, if sum and count are integersand average is a double • Integer division truncates the quotient to an int, which is then coerced to floating-point (without the fractional part) • Pascal avoids this with a special operator, div, for integer division average = sum / count;
Overloaded operators • C++ and Ada allow user-defined overloaded operators • Potential problems • Users can define nonsense operations • Readability may suffer, even when the operators make sense • Used well, however, a program can be made more readable
Overloaded Operators Example // Overload + operator to add two Box objects. Box operator+(const Box& b) { Box box; box.length = this->length + b.length; box.breadth = this->breadth + b.breadth; box.height = this->height + b.height; return box; } private: double length; // Length of a box double breadth; // Breadth of a box double height; // Height of a box }; class Box { public: double getVolume(void) { return length * breadth * height; } void setLength( double len ) { length = len; } void setBreadth( double bre ) { breadth = bre; } void setHeight( double hei ) { height = hei; } }
Overloaded Operators Example // volume of box 1 volume = Box1.getVolume(); cout << "Volume of Box1 : " << volume <<endl; // volume of box 2 volume = Box2.getVolume(); cout << "Volume of Box2 : " << volume <<endl; // Add two object as follows: Box3 = Box1 + Box2; // volume of box 3 volume = Box3.getVolume(); cout << "Volume of Box3 : " << volume <<endl; return 0; } // Main function for the program int main( ) { Box Box1; // Declare Box1 of type Box Box Box2; // Declare Box2 of type Box Box Box3; // Declare Box3 of type Box double volume = 0.0; // Store the volume of a box here // box 1 specification Box1.setLength(6.0); Box1.setBreadth(7.0); Box1.setHeight(5.0); // box 2 specification Box2.setLength(12.0); Box2.setBreadth(13.0); Box2.setHeight(10.0);
Type conversions • A narrowing conversion is to convert an object to a type that cannot include all of the values of the original type • For example, float to int • A widening conversionis that an object is converted to a type that can include at least approximations to all of the values of the original type • For example, int to float • Conversion of large integers results in loss of precision • Widening conversions are nearly always safe
Type conversions • A mixed-mode expressionis the situation that has operands have different types • A corecionis an implicit type conversion • Coercions decrease the type error detection ability of the compiler • Most languages allow mixed-mode expressions in which all numeric types are coerced as necessary with widening conversions • Ada is an exception, with virtually no mixed-mode expressions or coercions inti, j; float k; j= i + k;
Explicit type conversions • Explicit type conversions are called casts • Examples • Ada • IntegerIndex is cast to Float using: Float( Index ) • Java • Doublespeed is cast to int using: (int) speed
Relational and Boolean Expressions • A relational expression • Uses relational operators (such as < and ==) and operands of various types • Evaluates to some Boolean representation • Operator symbols used vary among languages • Some symbols for not equal != /= <> .NE. • A Boolean expression has Boolean operands and the result is Boolean Boolean operators For Different Languages • FORTRAN 77 FORTRAN 90 C Ada • .AND. and && and • .OR. or || or • .NOT. not ! not • xor
Relational and Boolean expressions • Observations concerning C • C had no Boolean type prior to C99 • It uses int type with 0 for false and 1 for true • An expression like a<b returns 0 or 1 • C gives higher precedence to AND than to OR • This does not agree with the conventions of Boolean algebra • In C, the expression a>b>c is still legal • 11>7>5 evaluates to false • since 11>7 evaluates to be 1 • 1 > 5 evaluates to false
Short circuit evaluation • A short-circuit evaluation is one where the result is determined, without evaluating all the operands and/or operators • C, C++, and Java use short-circuitevaluation for the usual Boolean operators (&& and ||) • They also provide bitwise Boolean operators that are not short circuit (& and |) (13 * a) * (b / 13 -1) If a= 0, then there is no need to evaluate (b/13 -1)
Short circuit evaluation • Ada has both short-circuit and traditional Boolean operators • Traditional: and, or • Short-circuit: and then, or else • Short-circuit evaluation may cause an error when the program relies on side effects in expressions • For example: (a > b) || ( (b++) < 3 ) • If a>b, then b will not be incremented
Assignment statements • The assignment operator symbol is typically = or := • = in Fortran, Basic, PL/I, C, C++, and Java • := in Algol, Pascal, and Ada • When = is used, it should not be overloaded for the relational operator for equality • PL/I does this • A = B = C; assigns a Boolean to A
Assignment statements • Some assignment statement variety • Multiple targets • PL/I: A, B = 10 • C: a = b = c; • Compound assignment operators • C, C++, and Java: sum += increment; • Unary assignment operators • C, C++, and Java: a++; • What effect of this • C, C++, and Java • What this means of the following? • Tradeoff between readability and writability! - count ++ n = (a == b) ? count : index = 10;
//compute –x++; #include <stdio.h> #include <stdlib.h> int main(){ int x = 10, R = 0; printf("x has the value %d \n", x); printf("-x has the value %d \n", -x); printf("x has the value %d \n", x); printf("-x has the value %d \n", -x++); printf("x has the value %d \n\n", x); printf("-x has the value %d \n", -x++); printf("x has the value %d \n\n", x); printf("-x has the value %d \n", -x++); printf("x has the value %d \n\n", x); R = -x++; printf("R is %d;\t X is %d \n", R, x); system("pause"); return 0;}
x has the value 10 //x’s value in storage -x has the value -10 //-x x has the value 10 //x’s value in storage -x has the value -10 //-x++ x has the value 11 //x’s value in storage -x has the value -11 //-x++ x has the value 12 //x’s value in storage -x has the value -12 //-x++ x has the value 13 //x’s value in storage R is -13; X is 14 //set R = -x++; R has value –x, the x++ Press any key to continue . Conclusion, -x did not change the value of x in the storage for x..
Assignment statements • C, C++, and Java treat = as an arithmetic binary operator that returns the value assigned to the LHS • This was inherited from ALGOL 68 • Useful in • Perhaps convenient in • Just poor practice in • Reliability disadvantage • Another kind of expression side effect • Readability disadvantage • Assignments on the RHS of expressions are easy to miss • The expression cannot be read as an expression denoting a value while ( (ch= getchar() ) != EOF ) { } a = b * (c = d * 2 + 1) + 1; a = b + ( c = d / b++ ) – 1;
Multiple Assignments • Perl, Ruby, and Lua allow multiple-target multiple-source assignments ($first, $second, $third) = (20, 30, 40); Also, the following is legal and performs an interchange: ($first, $second) = ($second, $first);
Assignment statements • Problem • = and == are similar, but have completely different meanings • This is not so bad if the compiler can catch mistakes • Suppose = is inadvertently used for == in C or C++ • The compiler does not detect the error because . . . • = returns the value of b • This value is treated as a Boolean • false if b == 0 • true if b is non-zero if ( a = b ) { } Extension of Boolean expression to include =
Mixed-mode assignment • In FORTRAN, C, and C++, any numeric value can be assigned to any numeric scalar variable • Whatever coercion that is necessary is done • In Pascal, integers can be assigned to floats, but floats cannot be assigned to integers • The programmer must specify whether the conversion from real to integer is truncated or rounded • In Java and C#, only widening assignment coercions are done • In Ada, there is no assignment coercion
Summary • Expressions • Operator precedence and associativity • Operator overloading • Mixed-type expressions • Various forms of assignment
Assignment Four • Expressions • Operator precedence and associativity • Operator overloading • Mixed-type expressions • Various forms of assignment