Sie sind auf Seite 1von 53

ITCS332: Organization of Programming Languages Chapter 5 Names, Bindings, Type Checking, and Scopes

ISBN 0-321-33025-0

Chapter 5 Topics

.ITCS332

Introduction Names Variables The Concept of Binding Type Checking Strong Typing Type Compatibility Scope and Lifetime Referencing Environments Named Constants
5-2

by Dr. Abdel Fattah Salman

Introduction
Imperative languages are abstractions of von Neumann computer architecture. The 2 primary components are:
Memory: stores both data and instructions. Processor: provides operations to modify the contents of memory. The abstractions in the L for memory cells are variables.

Variables characterized by a collection of attributes: Name, Address, Value, Type, Lifetime, and Scope

.ITCS332

by Dr. Abdel Fattah Salman

5-3

Names
Names are one of the fundamentals attributes of vars. Names are associated with labels, arrays, subprograms, formal parameters, A name is a string of characters used to identify some entity in a program. In most PLs names have the same form: a letter followed by a string consisting of letters, digits, and underscore (_). In recent languages _ is replaced with Camel notation Design issues for names:

.ITCS332

Maximum length? Are connector characters allowed? Are names case sensitive? Are special words reserved words or keywords?
by Dr. Abdel Fattah Salman 5-4

Names (continued)
Length
If too short, names are less readable and meaningless. The name length affects the size of symbol table. Language examples: FORTRAN IV: maximum 6 COBOL: maximum 30 FORTRAN 90 and ANSI C: maximum 31 Ada and Java: no limit, and all characters are significant C++: no limit, but implementers often impose one External names (those defined outside functions) limited to 31.

.ITCS332

by Dr. Abdel Fattah Salman

5-5

Names (continued)
Connectors ( Underscore or space).
Pascal, Modula-2, and FORTRAN 77 don't allow Others do In recent languages underscore is replaced by camel notation In some versions of FORTRAN spaces were used (ignored by a compiler).

Case sensitivity
Disadvantage: readability (names that look alike are different)
worse in C++ and Java because predefined names are mixed case (e.g. IndexOutOfBoundsException)

C, C++, and Java names are case sensitive


The names in other languages are not
.ITCS332

by Dr. Abdel Fattah Salman

5-6

Names (continued)

Special words in PLs are used :


To make programs more readable by naming actions to be performed To separate syntactic entities of programs: (statement clauses). Special words are 2 kinds: keywords and reserved words. A keyword is a word that is special only in certain contexts, as in Fortran Real VarName (Real is a data type followed with a name, therefore Real is a keyword). For example: Real = 3.4 (Real is a variable). A reserved word is a special word that cannot be used as a userdefined name. Reserved words are better than keywords because the ability to redefine keywords can be confusing such as in Fortran:
Integer real Real integer

.ITCS332

by Dr. Abdel Fattah Salman

5-7

Variables
A variable is an abstraction of a memory cell or a collection of memory cells. Variables - names of memory cells. Variables can be characterized as a sextuple of attributes: Name, Address, Value, Type, Lifetime, Scope Name Most variables have names, but not all variables have them Address - the memory address with which it is associated (called L-value). A variable may have different addresses at different times during execution: a function has a local variable allocated on the run-time stack. A variable may have different addresses at different places in a program: 2 subprograms have local variable with the same name.
.ITCS332

by Dr. Abdel Fattah Salman

5-8

Variables
Aliases: If multiple names can be used to access the same memory location, they are called aliases. Aliases are created via: Pointers: 2 pointer are aliases when they point to the same memory location. Reference variables: The pointer when dereferenced and the variable name are aliases. Unions in C and C++. Subprogram parameters. Aliases are harmful to readability (program readers must remember all of them): if variables sum and total are aliases, any change to total also changes sum and vice versa. Aliases makes program verification more harder.
.ITCS332

by Dr. Abdel Fattah Salman

5-9

Variables Attributes (continued)


Type - determines the range of values of variables and the set of
operations that are defined for values of that type; in the case of floating point, type also determines the precision.

Value - the contents of the memory location with which the


variable is associated Physical cells (individually addressable units) are byte-sized which is small for most vars. Abstract memory cell - the physical cell or collection of cells required by a variable with which it is associated. FP variable as a single abstract cell occupies 4 bytes. A variable value is its r-value. To access the r-value, the Lvalue must be determined first. The L-value of a variable is its address The r-value of a variable is its value
.ITCS332

by Dr. Abdel Fattah Salman

5-10

The Concept of Binding


A binding is an association, such as between an attribute and an entity, or between an operation and a symbol Binding time is the time at which a binding takes place. Language design time -- bind operator symbols to operations such as the asterisk *-multiplication operator) Language implementation time a data type such as floating point type or int type is bound to a range of possible values. Compile time -- bind a variable to a type in C or Java Load time -- bind a FORTRAN 77 variable to a memory cell (or a C static variable). Link time -- A call to a library function is bound to the function code Runtime -- bind a nonstatic local variable to a memory cell
.ITCS332

by Dr. Abdel Fattah Salman

5-11

Possible Binding Times


Consider a C assignment statement: count = count + 5; The binding and binding times for this statement are: The type of count is bound at compile time. The possible values of count are bound at compiler design time. The meaning of operator + is bound at compile time when the type of its operands have been determined. The internal representation of literal 5 is bound at compiler design time. The value of count is bound at execute time of this statement. A complete understanding of binding times for the attributes of program entities is prerequisite for understanding the semantics of a PL.
.ITCS332

by Dr. Abdel Fattah Salman

5-12

Static and Dynamic Binding


A binding is static if it first occurs before run time and remains unchanged throughout program execution. A binding is dynamic if it first occurs during execution or can change during execution of the program. The binding of a variable to a storage cell in a virtual memory environment is complex, because the page/segment containing the memory cell may be swapped in and out of memory many times during program execution. Such variables are bound and unbound repeatedly. This binding is performed by computer hardware and the changes are invisible to the program and user.

.ITCS332

by Dr. Abdel Fattah Salman

5-13

Type Binding
Before a variable can be referenced, it must be bound to a data type. The 2 important aspects of this binding are: How is a type specified? When does the binding take place? If static type binding: the type may be specified by either an explicit or an implicit declaration. An explicit declaration is a program statement used for declaring the types of variables- lists variable names and specifies their type. An implicit declaration is a default mechanism (convention) for specifying types of variables (the first appearance of the variable in the program). Most PLs require explicit declarations of ALL program variables. FORTRAN, PL/I, BASIC, Perl, JavaScipt provide implicit declarations Advantage: writeability Disadvantage: implicit declaration can be detrimental to reliability because they prevent the compiler from detecting some typographical and programmer error. (less trouble with Perl).
.ITCS332

by Dr. Abdel Fattah Salman

5-14

Type Binding
Some problems of implicit declaration can be avoided by requiring names for specific types to begin with particular special character. In Perl: If a names begins with $ it is a scalar (string or numeric); if it begins with @, it is an array; if it begins with %, it is a hash structure. This creates different namespaces for different type variables. In C and C++: Declarations specify type and other attributes but do not cause allocation of storage. Definitions specify attributes and cause allocation of storage. A variable may have MANY compatible declarations but ONE definition. Prototypes declare names and interfaces but not the code of functions
.ITCS332

by Dr. Abdel Fattah Salman

5-15

Dynamic Type Binding


With Dynamic Type Binding (JavaScript and PHP), the type of a variable is NOT specified by a declaration or by default conventions. Variable is bound to a type when it is assigned a value. When the assignment statement is executed, the variable being assigned is bound to the type of the value of the RHS expression. In JavaScript and PHP: a program may contain a statement:
list=[2,4.33,6,8];

This statement causes the name list to be a single-dimensional array regardless of previous type of name list. On the other hand, the statement list = 17.3; defines the name list as a scalar variable . Advantage: Programming flexibility (generic program units) Disadvantages: Makes a program less reliable and makes Type error detection by the compiler is difficult- Incorrect type of RHS of assignments are NOT detected as errors; rather, the type of the LHS is changed to the incorrect type.
Suppose i and x are currently storing scalar numeric values, and y is storing an array. Suppose that the JavaScipt program needs the assignment i=x; but because of a keying error, we wrote i=y;
.ITCS332

by Dr. Abdel Fattah Salman

5-16

Dynamic Type Binding


No error will be detected i is simply changed to an array. In a L with static type binding, the compiler will detect the error and the program will not get to execution. High cost: Large execute time (dynamic type checking and interpretation) Type checking must be done at run time. Every variable must have a run-time descriptor associated with it to maintain the current type. The storage needed for the value of a variable must be of varying size, because different type values require different amounts of storage. Ls with dynamic type binding for variables must be implemented using pure interpreters rather than compilers. Pure interpretation typically is slower than compilation by at least ten times. Ls with static type bindings are seldom implemented by pure interpretation, because programs in these Ls can be easily translated to very efficient machine codes.
.ITCS332

by Dr. Abdel Fattah Salman

5-17

Dynamic Type Binding


Type Inferencing (ML, Miranda, and Haskell) Rather than by assignment statement, types are determined from the context of the reference The function declaration: fun circumf(r)= 3.14159 * r * r specifies a function takes a FP argument and produces a FL result The types are inferred from the type of the constant. The function: fun times10(x) = 10 * x; specifies both the argument and the result are inferred to be int. In the function fun square (x) = x * x; ML determines the types of argument and result from the operator * as default numeric int. If square is called with FP value as square (2.5), it would cause error. If we want square to accept FP arguments, it could be written fun square (x) : real = x * x; or fun square (x : real ) = x * x; or fun square (x) = (x : real ) * x; or fun square (x) : real = x * (x : real);
.ITCS332

by Dr. Abdel Fattah Salman

5-18

Variable Attributes (continued)


The fundamental character of imperative languages is determined by the design of the storage bindings for its variables. Storage Bindings & Lifetime Allocation the process of getting a cell from some pool of available memory cells for a variable. Deallocation - the process of putting a memory cell unbounded from a variable back into the pool The lifetime of a variable is the time during which it is bound to a particular memory cell. The lifetime of a variable begins when it is bound to a specific cell and ends when it is unbound from that cell. According to the storage binding, scalar variables are classified into 4 categories:

.ITCS332

static, stack-dynamic, explicit heap-dynamic, and implicit heap-dynamic.


by Dr. Abdel Fattah Salman 5-19

Categories of Variables by Lifetimes


Static variables are bound to memory cells before program execution begins
and remains bound to the same memory cells until program execution terminates, e.g., all FORTRAN 77 variables, C static variables. Sometimes it is convenient to have variables declared in subprograms be history-sensitive: have them retain values between separate executions of the subprogram. Advantages: efficiency (All addressing of static variables is direct), no runtime overhead is incurred for allocation and deallocation of static vars. Disadvantage: lack of flexibility (recursion can not be supported); Storage can not be shared among vars.

Stack-dynamic variables are those whose storage bindings are created


for variables when their declaration statements are elaborated and whose types are statically bound. Elaboration refers to the storage allocation and binding process indicated by the declaration which takes place when execution reaches the code to which the declaration is attached. Elaboration occurs during run time.
.ITCS332

by Dr. Abdel Fattah Salman

5-20

Categories of Variables by Lifetimes


For example, the variable declaration that appears at the beginning of a Java method are elaborated when a method is called and the variables defined by these declarations are deallocated when the method completes its execution. Some languages allow declarations to occur anywhere a statement can appear. All of the Stack-dynamic variables declared in a function may be bound to storage at the beginning of execution of the function. Recursive subprograms require some form of dynamic local storage so that each active copy of the recursive subprogram has its own version of the local variables. All attributes except storage (address) are statically bound to stack-dynamic scalar variables. Local variables in C++, C# subprograms and Java methods are by default stackdynamic. Advantage: allows recursion; conserves storage Disadvantages: Overhead of allocation and deallocation Subprograms cannot be history sensitive Inefficient references (Slower access because indirect addressing is needed)
by Dr. Abdel Fattah Salman 5-21

.ITCS332

Categories of Variables by Lifetimes


Explicit heap-dynamic variables are nameless (abstract) memory cells that
are allocated and deallocated by explicit run-time instructions specified by the programmer. These variables are allocated from and deallocated to the heap, and can only be referenced through pointer or reference variables. An explicit heap-dynamic variable has 2 variables associated with it: a pointer or a reference variable through which the heap-dynamic variable can be accessed, and the heap-dynamic variable itself. An explicit heap-dynamic var is created by an operator (new in C++) or a call to a system function provided for this purpose. It is deallocated by delete in C++ int *intnode; // create a pointer intnode = new int; // create the heap-dynamic var delete intnode; // deallocate the heap-dynamic var pointed by intnode. Referenced only through pointers or references, e.g. dynamic objects in C++ (via new and delete), all objects in Java Advantage: provides for dynamic storage management Disadvantage: inefficient and unreliable
by Dr. Abdel Fattah Salman 5-22

.ITCS332

Categories of Variables by Lifetimes


Implicit heap-dynamic variables are bound to heap storage only when they are assigned values. All their attributes are bound every time they are assigned. They are just names that adapt to whatever use they are asked to use.
all variables in APL; all strings and arrays in Perl and JavaScript

Advantage: variables have the highest degree of flexibility Disadvantages: Inefficient, because all attributes are dynamic large run-time overhead for binding ALL attributes.. Loss of error detection by the compiler They have the same storage management problems as explicit heap-dynamic variables.
.ITCS332

by Dr. Abdel Fattah Salman

5-23

Type Checking
Generalize the concept of operands and operators to include subprograms and assignments. Subprograms are as operators whose operands are their parameters. The assignment symbol is as a binary operator, with its target variable and its expression being the operands. Type checking is the activity of ensuring that the operands of an operator are of compatible types A compatible type is one that is either legal for the operator, or is allowed under language rules to be implicitly converted, by compilergenerated code, to a legal type: int + real causes int to be converted (coerced) to real. This automatic conversion is called a coercion. A type error is the application of an operator to an operand of an inappropriate type
.ITCS332

by Dr. Abdel Fattah Salman

5-24

Type Checking (continued)


If all type bindings of variables to types are static, then nearly all type checking can be statically- Static type binding. Dynamic type binding requires type checking at run time. Some Ls such as JavaScript and PHP allow only dynamic type checking . It is better to detect errors at compile time than at run time because the earlier correction is usually less costly. The penalty for static checking is reduced programming flexibility. Type checking is complicated when a L allows a memory cell store values of diff types at different times during execution. In these cases, type checking must be dynamic and requires the run-time system to maintain the type of the current value of such memory cells. A strongly typed L is one in which each name in a program has a single type associated with it and that type is known at compile time. A programming language is strongly typed if type errors are always detected. This requires that the types of all operands can be determined at compile or run times. .ITCS332 by Dr. Abdel Fattah Salman 5-25

Strong Typing
Advantage of strong typing: allows the detection of the misuses of variables that result in type errors Language examples:
FORTRAN 77 is not: parameters, EQUIVALENCE Pascal is not: variant records C and C++ are not: parameter type checking can be avoided; unions are not type checked. Expressions in Java are strongly typed. The value of strong typing is weakened by coercion. Ls with great deal of coercion (Fortran, C, C++, are significantly less reliable than those with little coercion such as Ada. Java and C# have half as many assignment type coercion as C++, so their error detection is better than C++. Ada is, almost (UNCHECKED CONVERSION is loophole) (Java is similar).
.ITCS332

by Dr. Abdel Fattah Salman

5-26

Strong Typing (continued)


Coercion rules strongly affect strong typing--they can weaken it considerably (C++ versus Ada) Although Java has just half the assignment coercions of C++, its strong typing is still far less effective than that of Ada

.ITCS332

by Dr. Abdel Fattah Salman

5-27

Name Type Compatibility


The design of the type compatibility rules of a L is important, because it influences the design of the data type and the operations provided for values of those types. There are 2 kinds of compatibility methods: name compatibility and structure compatibility . Name type compatibility means the two variables have compatible types ONLY if they are in either the same declaration or in declarations that use the same type name Easy to implement but highly restrictive: Subranges of integer types are not compatible with integer types Formal parameters must be the same type as their corresponding actual parameters (Pascal) type indextype is 1 .. 100; count : integer; index : indextype; The variables count and index are not compatible count can not be assigned to index or vice versa.
.ITCS332

by Dr. Abdel Fattah Salman

5-28

Structure Type Compatibility


Structure type compatibility means that two variables have compatible types if their types have identical structures Structure type compatibility is more flexible than name type compatibility, but harder to implement : Under name type compatibility only 2 type names must be compared to determine compatibility. Under structure type compatibility the entire structures of the 2 types must be compared which is difficult. Consider the problem of 2 structured types: Are two record types compatible if they are structurally the same but use different field names? Are two array types compatible if they have the same element type but have diff subscripts ranges? (e.g. [1..10] and [0..9]) Are two enumeration types compatible if they have the same number of components and spell their components differently? With structure type compatibility, you cannot differentiate between types of the same structure (e.g. different units of speed, both float): type celsius = float; fahrenheit = float; Variables of these 2 types are compatible under structure type compatibility, allowing them to be mixed in expressions.
by Dr. Abdel Fattah Salman 5-29

.ITCS332

Structure Type Compatibility


Ada uses name type compatibility but provides 2 type constructs: subranges and derived types. A derived type is a new type that is based on some previously defined type with which it is incompatible, although it may have identical structure. Derived types inherit all the properties of their parent types.
type celsius is new float; type fahrenheit is new float;

Variables of these 2 derived types are incompatible, although their structures are identical. Variables of both types are incompatible with any other FP type. Lierals are exemption from the rule: a literal 3.0 has the type universal real and compatible with any FP type. An Ada subtype is a possibly range-constrained version of an existing type. A subtype is compatible with its parent type. Subtype small_type is integer range 0..99; Variables of subtype small_type are compatible with integer variables.
.ITCS332

by Dr. Abdel Fattah Salman

5-30

Structure Type Compatibility


For variables of Ada unconstrained array types structure compatibility is used:
type vector is array (integer range <>) of integer; vector1: vector (1..10); vector2: vector (11..20); The 2 objects vector1 and vector2 are compatible although they

have different names and different subscript ranges, because for objects of unconstrained array types, structure compatibility rather than name compatibility is used. Because both types have 10 elements and the elements are of type integer, they are compatible. Consider the following Ada declarations of constrained anonymous types
A: array(1..10)of integer; A has anonymous unique type. B: array(1..10)of integer; The 2 arrays A and B would be of anonymous but distinct incompatible

types, though they structurally identical. The multiple declaration: C, D: array(1..10)of integer; creates 2 anonymous types: one for C and one for D, which are incompatible. So, C and D are not compatible.
.ITCS332

by Dr. Abdel Fattah Salman

5-31

Structure Type Compatibility


The multiple declaration is treated as the following 2 declarations: C: array(1..10)of integer; D: array(1..10)of integer; In the following example: Type List_10 is array(1..10) of integer; C, D: List_10; Arrays C and D are compatible. C uses structure type compatibility for all types except structures and unions. Every structure and union declaration creates a new type that is not compatible with ant other type. Typedef does not introduce a new type; it simply defines a new name for an existing type. So, any type defined with typedef is equivalent to its parent type. C++ used name compatibility. OO Ls such as Java and C++ bring a new type compatibility: object compatibility.
.ITCS332

by Dr. Abdel Fattah Salman

5-32

Variable Attributes: Scope


The scope of a variable is the range of statements over which it is visible. A variable is visible in a statement if it can be referenced in it. Scope rules determine how references to variables declared outside the currently executing function or block are associated with their declarations and their attributes. A variable is local in a program unit/block if it is declared there. The nonlocal variables of a program unit/block are those that are visible within a program unit/block but not declared there. The scope rules of a language determine how references to names are associated with variables. There are 2 kinds of a variable scope: static and dynamic. Static scoping is so named because the scope of a variable can be determined statically: prior to execution.
.ITCS332

by Dr. Abdel Fattah Salman

5-33

Static Scope
There are 2 categories of static-scoped Ls: Ls in which subprograms can be nested creating nested static scopes, and Ls in which subprograms cannot be nested . Java and PHP allow nested subprograms, but C-based Ls do not. In static-scoped Ls: to connect a name reference to a variable, you (or the compiler) must find the statement in which it is declared. Search process: search declarations, first locally, then in increasingly larger enclosing scopes, until one is found for the given name. Enclosing static scopes (to a specific scope) are called its static ancestors; the nearest static ancestor is called a static parent. In the next example suppose a reference is made to a variable x in sub1:
.ITCS332

by Dr. Abdel Fattah Salman

5-34

Scope (continued)
procedure Big is x: integer; procedure sub1 is begin -- of sub1 ... x ... end; -- of sub1 procedure sub2 is x: integer; begin -- of sub2 ... end; -- of sub2 begin -- of Big ... end; -- of Big
.ITCS332

Under static scoping: the reference to x in sub1 is to the x defined in Big. The presence of predefined names complicates this process: in this case the search for the meaning of a variable begins with the list of predefined names, even before the local scope declarations are checked.

by Dr. Abdel Fattah Salman

5-35

Scope (continued)
Variables can be hidden from other units by having a "closer" variable with the same name:
void sub (){ // The reference to count in the while loop is to to that loops local count. int count; // The count of sub is hidden from the code inside the whiles loop. ... while (... ) { int count; count++; ... } ... }

C++ and Ada allow access to these "hidden" variables Ada uses selective references (operator): unit.name In C++: Global variables can be accessed using the scope operator (::) class_name::name
.ITCS332

by Dr. Abdel Fattah Salman

5-36

Blocks
A block is a code section with its own local variables and restricted scope. Blocks variables are stack-dynamic: they are allocated storage when the block is entered and deallocated when it is exited. Ada blocks are specified with declare clause. C-based Ls allow any compound statement (a statement sequence surrounded by matched braces) to have declarations and thus define a new scope. Compound statement is a block.
Examples: for (...) { int index; ... } Ada: declare LCL : FLOAT; begin ... end .ITCS332 by Dr. Abdel Fattah Salman C and C++:

5-37

Blocks
C++ allows variables definitions to appear anywhere in functions. When a definition appears at a position other than at the beginning of a function, but not within a block, that variables scope is from its definition statement to the end of the function. The for statements of C++, Java, and C# allow variable definitions in their initialization expressions. The scope of such a variable is restricted to the for construct. In C++, Java , and C#: The scope of a class variable is the whole class in which it is defined. The scope of a variable defined in a method starts at the definition.

.ITCS332

by Dr. Abdel Fattah Salman

5-38

Evaluation of Static Scoping


Assume MAIN calls A and B A calls C and D B calls A and E Tree representation of a program
MAIN A C D B E C D E A B MAIN

.ITCS332

by Dr. Abdel Fattah Salman

5-39

Static Scope Example


A graph of potential program calls A graph of desired program calls
MAIN MAIN

A C D

B E

A C D

B E

.ITCS332

by Dr. Abdel Fattah Salman

5-40

Static Scope (continued)


Suppose that after the program has been developed and tested, the spec is changed so that D must now access some data in B Solutions: Put D in B (but then C can no longer call it and D cannot access A's variables) Move the data from B that D needs to MAIN (but then all procedures can access them) Same problem for procedure access Overall: static scoping often encourages many globals. One solution to the problems of static scoping is an encapsulation construct ch 11.

.ITCS332

by Dr. Abdel Fattah Salman

5-41

Dynamic Scope
Dynamic Scope is based on calling sequences of program units, not their spatial textual layout (temporal versus spatial). So the scope is determined at run time. References to variables are connected to declarations by searching back through the chain of subprogram calls that forced execution to this point

.ITCS332

by Dr. Abdel Fattah Salman

5-42

Scope Example
procedure Big is x : integer; procedure sub1 is begin of x end ; of procedure sub2 is x : integer; begin of end; of begin of ... end; of
.ITCS332

Assume dynamic rules apply to nonlocal references.

sub1 sub1

sub2 sub2 Big Big

The meaning of var x in sub1 is dynamic. It may reference x from either declaration of x, depending on the calling sequence. Begin the search with local declarations. If not found, the declarations of the dynamic parent or calling procedure are searched.

by Dr. Abdel Fattah Salman

5-43

Scope Example
The search continues in that procedures dynamic parent and so forth, until a declaration of x is found. If none is found in any dynamic ancestor, it is a run-time error. In dynamic scoping: Consider 2 diff call sequences for sub1: Big calls sub2 which call sub1. Search starts at local proc sub1 to its caller sub2, where a declaration of x is found. So, the reference to x is to the x declared in sub2. Sub1 is called from Big. The dynamic parent of sub1 is Big, and the reference is to the x declared in Big. In static scoping: the reference to x in sub1 will be to Bigs in both call sequences.
.ITCS332

by Dr. Abdel Fattah Salman

5-44

Scope Example
MAIN - declaration of x SUB1 - declaration of x ... call SUB2 ... end SUB1 SUB2 ... - reference to x ... end SUB2 ... call SUB1 ...
.ITCS332

MAIN calls SUB1 SUB1 calls SUB2 SUB2 uses x

by Dr. Abdel Fattah Salman

5-45

Scope Example
Static scoping Reference to x is to MAIN's x Dynamic scoping Reference to x is to SUB1's x Evaluation of Dynamic Scoping: Advantage: convenience Disadvantage: Less reliable programs than static scoping Inability to statically type check references to nonlocals. poor readability. Accesses to nonlocal vars in dynamic-scoped Ls take longer than accesses to nonlocals when static scoping is used.
.ITCS332

by Dr. Abdel Fattah Salman

5-46

Scope and Lifetime


Scope and lifetime are sometimes closely related, but are different concepts Consider a static variable in a C or C++ function: A var that is declared in function using static is statically bound to the scope of that function and is statically bound to the storage. Its scope is static and local to the function. Its lifetime extends over the entire execution of the program. Consider the following C++ functions:
Void printheader() } Void compute() { int sum; Printheader(); } { /* end of printheader */

/* end of compute

*/

The scope of a var sum is completely contained within the compute function. The lifetime of sum extends over the time during which printheader executes The binding of sum to storage continues until the termination of compute.
.ITCS332

by Dr. Abdel Fattah Salman

5-47

Referencing Environments
The referencing environment of a statement is the collection of all names that are visible in the statement In a static-scoped language, it is the local variables plus all of the visible variables in all of the enclosing scopes (ancestor scopes). In these Ls, the ref. environment is needed while that statement is being compiled, so code and data structures can be created to allow references to variables from other scopes during run time. In Ada, scopes can be created by procedure definitions. The referencing environment of a statement includes the local variables plus all of the variables declared in the procedures in which the statement is nested (excluding variables in nonlocal scopes that are hidden by declarations in nearer procedures). Each procedure definition creates a new scope and a new referencing environment
.ITCS332

by Dr. Abdel Fattah Salman

5-48

Referencing Environments
procedure Example is A, B : integer; ... procedure sub1 is x, y: integer; begin of sub1 ... < ------------------ 1 end ; of sub1 procedure sub2 is x: integer; ... procedure sub3 is x: integer; begin of sub3 ... < ------------- 2 end; of sub3 begin of sub2 ... < ----_-------- 3 end; of sub2 begin of Example ... < ------------- 4 end; of Example
.ITCS332

1 x, y of sub1, A, B of example 2 x of sub3, (x of sub2 is hidden), A and B of example 3 x of sub2, A and B of example. The variables declared in sub1 are stack- dynamic, so they are not bound to storage if sub1 is not in execution.
5-49

by Dr. Abdel Fattah Salman

Referencing Environments
A subprogram is active if its execution has begun but has not yet terminated In a dynamic-scoped language, the referencing environment is the local variables plus all visible variables in all active subprograms Assume that the only function calls are: main calls sub2 which calls sub1:
void sub1() { int a, b;

<----------- 1
} void sub2 () { int b, c; sub1; } void main () { int c, d; sub2 ( ); }
.ITCS332

/* end of sub1*/

1 a, b of sub1,

<----------- 2
/* end of sub2*/

<----------- 3
/* end of main*/
by Dr. Abdel Fattah Salman

c of sub2, d of main, (c of main, b of sub2 are hidden). 2 b, c of sub2, d of main, ( c of main is hidden). 3 c and d of main
5-50

Named Constants
A named constant is a variable that is bound to a value only ONCE when it is bound to storage Advantages: readability (Using pi instead of 3.14) and modifiability ( changing all occurrences of 3.14 to 3.14159 can be tedious and error-prone). Used to parameterize programs The binding of values to named constants can be either static (as in FORTRAN 95) or dynamic (as in Java). Named constants in Ls that use static binding of values are called manifest constants. Languages:
FORTRAN 90: constant-valued expressions Ada, C++, and Java: expressions of any kind C# has 2 kinds: constants defined with const (static) and those defined with readonly (dynamic).
.ITCS332

by Dr. Abdel Fattah Salman

5-51

Variable Initialization
It is convenient for a variable to have a value before the code in which it is declared begins execution. The binding of a variable to a value at the time it is bound to storage is called initialization. Binding a value to a named constant. If a variable is statically bound to storage, then binding and initialization occur before run time the initial value must be specified as a literal or constant expression. If the storage binding is dynamic, initialization is also dynamic and the initial values can be any expression. In most Ls, initialization is often done on the declaration statement, e.g., in Java int sum = 0; int ptrSum = &sum; char uob[ ] = University of Bahrain;
.ITCS332

by Dr. Abdel Fattah Salman

5-52

Summary
Case sensitivity and the relationship of names to special words represent design issues of names Variables are characterized by the sextuples: name, address, value, type, lifetime, scope Binding is the association of attributes with program entities Knowledge of binding times of attributes to entities is essential to understanding the semantics of PLs. Scalar variables are categorized as: static, stack dynamic, explicit heap dynamic, implicit heap dynamic Strong typing means detecting all type errors

.ITCS332

by Dr. Abdel Fattah Salman

5-53

Das könnte Ihnen auch gefallen