Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
COSC3306: Programming Paradigms Lecture 4: Imperative Programming Specifications Haibin Zhu, Ph.D. Computer Science Nipissing University (C) 2003 1 Contents Taxonomy Design Principles Control Flows Execution steps Undesirable Characteristics Desirable Characteristics 2 Taxonomy Control-driven or control-flow architectures: – Reduced Instruction Set Computers (RISC). – Complex Instruction Set Computers (CISC). – High-level Language Architectures (HLL). Data-driven or data-flow architectures. Demand-driven or reduction architectures. 3 Taxonomy In control-driven or control-flow architectures, – The flow of computation is determined by the instruction sequence, and data are gathered as an instruction needs them. In a data-driven or data-flow architectures, – It is controlled by the readiness or the availability of data. In demand-driven or reduction architectures, – An instruction is enabled for execution when its results are required as operands for another instruction that has already been enabled for execution. 4 Properties of an imperative language In general, a programming language that is characterized by the following three properties is called an imperative language, since its primary feature is a sequence of statements that represent commands. – The sequential execution of instructions, – The use of variables representing memory location values, and – The use of assignment statements to change the values of variables and to allow the program to operate on these memory location values. 5 Design Principles Imperative programming languages describe how a given sequence of operations computes the result of a given problem. In the imperative approach we are more concerned with how to formulate the solution in terms of our primitive operations. 6 Three categories of action Computational actions such as arithmetic operations. Control-flow actions such as comparisons and looping statements. Input-output actions such as read and write operations. 7 Memory location Imperative actions all have access to a common storage which consists of an arbitrary number of memory locations. Each memory location can be characterized by a state as the following: – It may contain a data, meaning that the location is allocated and containing data. – It may be undefined, meaning that the location is allocated but not yet containing data. – It may be unused, meaning that the location is not allocated. 8 Stable data Data stored in memory locations are stable. In other words, data contained in a memory location remains undisturbed and available for inspection until that memory location is deallocated or has a new data stored on it. An imperative action works by making changes in memory. 9 Possible changes Store data in a location. This action stores data in a memory location. Deallocate a memory location. This action changes the state of memory location to unused. Allocate a memory location. This action finds an unused memory location and changes its status to allocated. Retrieve a memory location. This action yields the data currently contained in a memory location. 10 Variables A major component of a computer system is the memory which is comprised of a large number of memory cells (locations). The memory is where the data can be stored. The memory cells must be named. 11 Functions of variable declaration In variable declaration we consider the memory locations in which the values of interest reside. The variable declaration performs three functions as the following: – It allocates an area of memory of a specified size. – It attaches a symbolic name to the allocated area of memory. This is called binding a name to memory locations. – It initializes the contents of the memory locations if there is any initialization. These are three important functions of variable declarations in most imperative programming languages. 12 Data Types The data type used in programming languages can be classified into either of two categories. – Scalar data type which is the simplest possible data types. – Structured data type, in which consist of some combination of scalar data types. Any data type has three associated components. – Type name which is the identifier used to designate the type in declaration. – A set of constants of that type which is a symbol for a value that may be assigned to a variable of compatible type. – A set of operations upon that type which are used to construct expressions for the type. 13 Type Equivalence An important question in the application of type to type checking is type equivalence, meaning that when are two types the same? This question can be answered in three different ways as the following. 14 Structural Equivalence Two data types are the same if they have the same structure, meaning that they are built in exactly the same way using the same type constructors from the same simple types. In other words, two sets are the same if they contain the same values. For example, the types t1 and t2 defined as following are structurally equivalent, if we were only concerned about the size of the index set. – – t1 array [1 . . 11] of integer; t2 array [0 . . 10] of integer; 15 Name Equivalence Two named types are equivalent if they have the same name. This is a stronger condition than structural equivalence, because a name can refer only to a single type declaration. Name equivalence is adopted in Ada language. For example, the types array1 and array2 defined as follows are name equivalence; as are age and integer. – – – type array1 is array (1 . . 10) of INTEGER; type array2 is new array1; type age is new INTEGER; In Ada, the keyword new enforces the name equivalence. 16 Declaration Equivalence Two type names that goes back to the same original structure declaration by a series of redeclarations are considered to be equivalent types. Modula-2 supports declaration equivalence, where in C language a mixture of structural and declaration equivalence is used. 17 An example For example, in the following declarations name1, name2, and name3 are all declaration equivalent, but not name equivalent. – – – – type name1 array[1 . . 10] of integer; name2 name1; name3 name2; Similarly, in the following Modula-2 declaration x and y are declaration equivalent variables. – VAR x, y : ARRAY[1 . . 10] of INTEGER; 18 Assignment Statements The notion that every value computed must be assigned to a memory location is performed by an assignment statement. For example, the following assignment statement is a typical action in which it changes the value of a variable (memory location value) known as class. class 10; The assignment symbol “” appears between the right and left sides. This assignment statement sets class to 10 and the old value of class is discarded. A similar example is the following assignment statement class 45; where the value 9 of the expression 45 is assigned as the value of class variable by ignoring the old value of variable. 19 Operand Evaluation An important design characteristic is the order of evaluation of operands in expressions. For example, in the following expression A 10; B A 10; the value of B is computed by taking the content of a memory location associated with variable A, thus B takes the value as 20. If an operand is a parenthesized expression, then all operators it contains must be evaluated before its value to be used as an operand. 20 Another example For example, in the evaluation of the following expression A 10; B 20; C (A B) 10; the value of C is computed by evaluating the value of the subexpression (AB), in which two operands A and B and one operator “” are involved. Thus C takes the value 3010 as the computed value. 21 Side Effects The important issue in imperative programming language design is the side effects from the evaluation of the expressions. If neither of the operands of an operator has side effects then operand evaluation order is irrelevant. For example, there is no side effects associated with the evaluation of the following subexpressions of the expression. A 10; B 20; C (A 5) (B 10); 22 An example In contrast, sometimes the evaluation of an operand has side effects. For example, the following C expression illustrates the situation where the stored value of A in memory to be increased by 10 first, and the second subexpression then taking this new stored value as its value. In this example, the side effect of the evaluation of the first subexpression causes the value of B to be evaluated to 50. A 10; B (A A 10) + (A 10); 23 To be continued Control constructs Functions and Procedures Control Flows Execution Steps Undesirable Characteristics Desirable Characteristics 24 Selection Constructs An array data structure supports random access to a sequence of elements of the same type. Random access means that elements can be selected by their position in the data structure. An assignment x A[i]; assigns to x the value of the ith element of array A. The assignment A[i] x; changes the value of ith element of array A to x. Occasionally an algorithm will contain a series of decisions in which a variable or expression is tested separately for each of the constant integral values it may assume, and different actions must be takes. 25 Examples One way of making such an effect is by using a list of if statements such as: if (condition1) action1; if (condition2) action2; . . . if (conditionN) actionN; 26 Examples For example, consider the following code if AB Sum Sum A; Acount Acount 1; if BA Sum Sum B; Bcount Bcount 1; 27 Alternatives An alternative is the switch multi-selection structure to handle such decision making. switch (expression) { case 1: action1; break; case 2: action2; break; . . . case N: actionN; break; default: actionX; break; } 28 Basic issues Selection structures vary from language to language, but they tend to agree on the following issues. – Case selections can appear in any order. – Case selections are not required to be consecutive, meaning that it is valid to have case-1 and case-4 without case-2 and case-3. – Case selections must be distinct with regard to actions of each case; otherwise we need to combine the actions to avoid any conflict. 29 Conditional Constructs A conditional statement as the following form if expression statement2 then statement1 else control flows through statement1 or statement2 if expression is true or false, respectively. A variant of this conditional statement is if expressionthen statement with no else component. In this form, the statement is executed only if expression is true. The conditionals can be nested as the following general form. if else expression1 then statement1 if expression2 then statement2 else if expression3 then statement3 else ... 30 Looping Constructs A program in an imperative programming language usually performs its task by executing a sequence of elementary steps repeatedly. – Looping constructs can be classified into two categories as the following: – Definite iteration loops in which the number of iterations is predetermined when control flows through construct. Indefinite iteration loops in which the number of iterations is not known when control flows through construct. 31 Looping Constructs In other words, the looping constructs are divided depending upon whether or not we can predict the number of times the loop will be executed. The syntax for indefinite iteration construct is as the following while conditional-expression do statement where the control flows through the execution of the statement which is called the body of the construct as soon as the conditional-expression is evaluated to true. 32 Looping Constructs In the following the loop is executed with index taking the values 0, 1, 2, … , 9 in order to initialize the corresponding array element with zero. index 0; while (index 10) { A[index] 0; index index 1; } 33 Looping Constructs The syntax for definite iteration construct is as the following for (expression1; expression2; expression3) body-of-loop; where control flows through the execution of the body-ofloop depending upon the value of the expression2. For example, in the following for (index 0; index 10; index) A[index] 0; the assignment A[index] 0; is executed with index taking the values 0, 1, 2, … , 9 on successive executions. 34 Unions We can construct a union of two types, in which can be formed by taking the set theoretic union of their sets of values. Union type come in two varieties. – Discriminated Unions: If a tag or discriminator is added to each element field to distinguish which type the element is. – Undiscriminated Unions: It lack the tag, and assumptions must be made about the type of any particular element. A language adopted discriminated and undiscriminated union is Modula-2, and C is a language adopted undiscriminated union. 35 Functions and Procedures Despite their distinct roles as operators and actions, functions and procedures are very similar to each other. The only difference between them is that functions return a result and procedures do not. No wonder one language such as C calls them both as functions and another language such as Modula-2 calls them both procedures. In general, a procedure or function declaration defines the components as: – A name for the declared procedure or function. – The formal parameters which are placeholders for input and output. – A body consisting of local declarations and statements. – An optional result type to address the data type of the returned result. 36 Control Flow Statement-Oriented Block-Oriented – Localize changes – Correct assumptions at the beginning and the end – No need to concern about conflicts names – Facilitate organization of a program – Explicit control information to descendant blocks 37 Figure 6.1 Control flows through a sequence of statements © 2003 Brooks/Cole Publishing / Thomson Learning™ 38 Figure 6.2 Control flows through a block © 2003 Brooks/Cole Publishing / Thomson Learning™ 39 Execution Steps for Imperative Programming An imperative program goes through several stages in order to be executed. – Compilation-linking-loading-execution Compilation: This process translates the program into a relocatable object code, meaning that the program and all individual subprograms are translated into an intermediate code compatible with the computer system. 40 Execution Steps for Imperative Programming Linking: This process incorporates the necessary libraries into the program. These libraries associated with subprograms are already programmed, debugged and compiled. The goal of linking process is to obtain a relocatable object code containing of all parts of the program including all library references satisfied. Loading: This is the process that a relocatable code is placed in memory for execution. This process requires converting relocatable object code to absolute format for execution. Execution: This is the process that the control flows through the execution of the statements of the program. 41 © 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 6.3 The Compile-Link-LoadExecute steps of program execution 42 Undesirable Characteristics for Imperative Programming Difficulty in Reasoning – The correctness of a program depends on the contents of each and every memory location. Referential Transparency Side Effects Indiscriminate Access Vulnerability Access No Overlapping Definitions 43 Referential Transparency A system is referentially transparent if the meaning of the whole can be determined solely from the meaning of its components. For example, in a mathematical expression such as F(x)G(x), we may substitute another function H for F, if we know that it produces the same values as F. In imperative programming languages we are not assured of this, because the meaning of the expression depends on the history of computation of the subexpressions. Indeed, if F or G change the value of their parameter or modify some global variables, we are not even certain that F(x)G(x) G(x)F(x). 44 Side Effects Imperative programming supports imperative operations that are performed not to obtain a value but rather for some side effect on the computations. For example, operators like or in C language have side effects, meaning that besides returning a value they also modify an underlying variable. Side effects can be convenient but they can also cause trouble, because the actions of retrieving the value and updating the variable might not happen at the same time, one at the time of expression evaluation and one at the termination of the execution. 45 Side Effects Consider – class_list[index] class_list[index] 0; In this statement, the intent is to store zero at the two consecutive positions in array. But depending on when index is updated, a position in array could be skipped and index might be increased only by 1. (sideeffect2.cpp) 46 Indiscriminate Access The problem of indiscriminate access is that, programmers can not prevent inadvertent access to variables or data structures. For example, suppose we want to provide a stack to be used in an Algol program. We would probably design the program as the following. 47 An example of Algol begin integer array S[1:100]; integer TOP; procedure PUSH(x); integer x; begin TOP TOP1; S[TOP]x; end; procedure POP(x); integer x; begin POP S[TOP]; TOP TOP1; end; TOP 0; ... uses of PUSH and POP end; ... 48 Explanation In this case, the variable S which is the stack must be declared in the same block as PUSH and POP so that it is visible from the bodies of PUSH and POP procedures. In addition, for the PUSH and POP procedures to be visible to their users, they must be declared in a block that contains all users. In this example, there is no guarantee that all users of the stack go through the PUSH and POP procedures in order to manipulate the data structure. 49 Vulnerability Access The problem of vulnerability access is that, under certain circumstances it is impossible to preserve access to a variable. Consider a very large Algol program. begin integer x; . . . . many lines of code begin . . . . many lines of code x x 1; . . . . many lines of code end; . . . . many lines of code end; In this example, we are supposing that there are so many lines of code between the definition and use of x variable. Let’s further suppose that in the process of maintaining this program 50 we decide that we need a new local variable in the inner block. Change a little bit If we pick x without realizing that it was already used in that block, it results the following program. begin integer x; . . . . many lines of code begin real x; . . . . many lines of code x x 1; . . . . many lines of code end; . . . . many lines of code end; In this case, with this modification access to the outer declaration of integer x has been blocked and the statement x x 1 now refers to the new real variable x. In other words, the new declaration of x has been interposed between the original definition of x and its use. Thus, the problem of vulnerability access is the inability to preserve access to a variable. 51 No Overlapping Definitions The problem of no overlapping definitions is the inability to control shared access to variables. As a consequence, it creates both a maintenance and security problem. 52 © 2003 Brooks/Cole Publishing / Thomson Learning™ Figure 6.4 Overlapping structures in a program 53 Desirable Characteristics for Imperative Programming Some of the issues involved in good programming can be outlined. No Implicit Inheritance – The default should not be to extend the scope of a variable to inner block. Distinguish Access to Data Structures – It should be possible to distinguish different data types of access. Decoupling Declarations – Declaration of definition, name access and allocation should be decoupled. 54 Desirable Characteristics for Imperative Programming Natural Form for Expressions – Write expressions as you might make them understanding. if (!(block_id<block_1)||!(block_id>=block_2)) or if ( (block_id>=block_1)|| (block_id<block_2)) Which is better? 55 Parenthesize to Resolve Ambiguity Parentheses specify grouping and can be used to make the intention more clear even when they are not required. – if (*&MASK ==BITS) – if (*&(MASK ==BITS)) – if ((*&MASK) ==BITS) – if (MASK ==BITS) 56 Break up Complex Expressions – The statement is more easy to understand when is broken into several pieces. *ptra+=(*ptrb = (2*index<(index_1-index_2)? array1[index++]:array2[index--]) If (2*index<(index_1-index_2) *ptrb=array1[index++]; else *ptrb=array2[index--]; *ptra+=*ptrb; 57 Summary Taxonomy Design Principles Control constructs Execution steps Undesirable Characteristics Desirable Characteristics 58