0% found this document useful (0 votes)
63 views36 pages

Slides 08 Programming Languages - UET CS - Talha Waheed - Names Bindings Type Checking and Scope

This document discusses variable names, bindings, type checking, and scope in programming languages. It covers design issues for variable names like maximum length and case sensitivity. It defines different types of bindings like static and dynamic bindings. It describes four categories of storage bindings for variables based on their lifetime - static, stack dynamic, explicit heap dynamic, and implicit heap dynamic. Finally, it discusses type checking and compatible types for operators.

Uploaded by

laraibnawaz86
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
63 views36 pages

Slides 08 Programming Languages - UET CS - Talha Waheed - Names Bindings Type Checking and Scope

This document discusses variable names, bindings, type checking, and scope in programming languages. It covers design issues for variable names like maximum length and case sensitivity. It defines different types of bindings like static and dynamic bindings. It describes four categories of storage bindings for variables based on their lifetime - static, stack dynamic, explicit heap dynamic, and implicit heap dynamic. Finally, it discusses type checking and compatible types for operators.

Uploaded by

laraibnawaz86
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 36

CS445 Programming Languages Slides 8

– Names, Bindings, Type Checking, Scope

By Talha Waheed, UET Lahore


Variable
Names
- Design issues:
- Maximum length?
- Are connector characters allowed?
- Are names case sensitive?
- Are special words reserved words or keywords?

Length
- FORTRAN I: maximum 6
- COBOL: maximum 30
- FORTRAN 90 and ANSI C: maximum 31
- Ada: no limit, and all are significant
- C++: no limit, but implementors often impose one

Design Issue: Readability and Writability get affected.


Variables
Connectors
- Pascal, Modula-2, and FORTRAN 77 don't allow
- Others do
- Design Issue: Enhances readability?
- Is ‘_’ or ‘__________’ valid variable names. What does it mean?

Case Sensitivity
- Advantage: Writability, different combinations of same alphabets
- Disadvantage: readability (names that look alike are different)
- worse in Modula-2 because predefined names mixed case
(e.g. WriteCard)
- ABC, aBC, (how many combinations are possible?)

- C, C++, Java, and Modula-2 names are case sensitive


- The names in other languages are not
Variables
Keywords

A keyword is a word that is special only in certain contexts e.g.

IF THEN = THEN THEN IF = ELSE ELSE ELSE = IF

- Disadvantage: poor readability

INTEGER REAL A variable real of type integer


REAL INTEGER A variable integer of type real

REAL X
REAL = 44.7

Reserve Words
A reserved word is special word that cannot be used as user-defined name
Variables
A variable is an abstraction of a memory location

It has 6 attributes (){name, address, value, type, lifetime, scope}

1: Variable Attribute: Name - not all variables (memory) have names.


2: Variable Attribute: Address - the memory with which it is associated
- A variable may have different addresses at different times during
execution (dynamic)
- A variable may have different addresses at different places in program

Aliases
- If two variable names can be used to access same memory location, they
are called aliases

- Aliases are harmful to readability


Aliases

- How aliases can be created:

- Pointers, reference variables,


- Pascal variant records,
- C and C++ unions, and
- FORTRAN EQUIVALENCE (and through parameters)

- Some of original justifications for aliases are no longer valid;


e.g. memory reuse in FORTRAN

- Solution: replace them with dynamic allocation


Variable
3: Variable Attribute - Value
- contents of memory location with which variable is associated

Abstract memory location - physical location or collection of locations


(e.g. in arrays) associated with a variable x = 10

The l-value of a variable is its address


The r-value of a variable is its value

3: Variable Attribute - Type


- determines range of values of variables and set of operations that are
defined for values of that type;

- in case of floating point, type also determines precision


Two Important Terms
Binding and Binding Time

A binding is association, such as between


attribute and entity (e.g. variable and its name),
or between operation and symbol (e.g. increment and ++).

Binding time is time at which binding of attribute


and entity takes place.
Possible Binding Times
1. Language design time
- binding of operator symbols to operations. e.g. := for assignment

2. Language implementation time


- bind floating point type to representation e.g. some IEEE format

3. Compile time
- bind variable name to data type in C or Java, e.g. int length;

4. Load time
- bind FORTRAN 77 variable to a memory cell
(or a C static variable)

5. Runtime/Execution Time
- dynamic memory allocation to local variable. e.g. p = new (int);
Static vs Dynamic Binding

A binding is static if it occurs before run time and remains


unchanged throughout program execution.

Vs.

A binding is dynamic if it occurs during execution or can


change during execution of program.
Type Binding
Design Issues:
1. How is a type specified?
2. When does the binding of type take place?

If type binding is static, it may be specified by either explicit or


implicit declaration

• explicit declaration is program statement used for declaring types of


variables float y; y=x|+z;
• implicit declaration is default mechanism for specifying types of
variables (first appearance of variable in program)

FORTRAN, PL/I, BASIC provide implicit declarations


Advantage: writability
Disadvantage: reliability is poor
Dynamic Type Binding
- Specified through assignment statement e.g. In APL
LIST <- 2 4 6 8
LIST <- 17.3

Advantage:
1. Flexibility (generic program units)
Disadvantages:
1. High cost (dynamic type checking and interpretation)
2. Type error detection by compiler is difficult
Type Inferencing
- In ML, Miranda, and Haskell
- Rather than by assignment statement, types are determined
from context of reference.
Storage Bindings
Allocation
getting a memory cell from some pool of available memory

Deallocation
putting unbound memory cell back into the pool

Lifetime
lifetime of variable is time during which it is bound to particular
memory location

Categories of variables by lifetimes


1. Static
2. Stack Dynamic
3. Explicit Heap Dynamic
4. Implicit Heap Dynamic
Storage Binding - 1. Static
• Bound to memory cells before execution begins and remains bound to same
memory cell throughout execution.

e.g.
• all FORTRAN 77 variables
• C static variables (e.g. static int number = 9;)
• (static variables in C++ class, created before first instantiation of class)

Advantages:
• Globally accessible variables – for message passing, flag settings
• Efficiency (direct addressing), no time wastage for allocation / deallocation
• History-sensitive (for local static variable support in functions)

Disadvantage:
• Lack of flexibility (no recursion),
• Storage can’t be shared among variables
Storage Binding - 2. Stack-dynamic
• Storage bindings created for variables when declaration statements elaborated.
– (If scalar, all attributes except address are statically bound.)

• Variable declarations at start of Java method elaborated when method called


– variables defined by those declarations deallocated when method completes execution.
• Fact(int n)
• {
• int x;
• } fact(Int n){
• n*fact(n-1);
• Allocated from run-time stack. Fac(3) = 3*fact(2)
• Fac(2) = 2* fact(1)

– e.g. local variables in Pascal and C subprograms (by default)

Advantage:
• Allows recursion - each active copy of recursive subprogram has its own version
of local variables.
• Conserves storage - all subprograms share same memory space for their locals.
Storage Binding - 3. Explicit heap-dynamic
• Allocated, deallocated by explicit directives, specified by programmer, which take
effect during execution
– Nameless (abstract) cells of heap memory accessed only through pointers or
references,
int *intnode; // Create a pointer of type int
intnode = new int; // Create the heap-dynamic variable
delete intnode; // Explicit Deallocation of variable to which intnode points

• Bound to type at compile time (static), bound to storage at creation (run time)
– dynamic objects in C++ (new, delete operators) or function call ( malloc /dealloc) in
C, all objects in Java.

• No deallocation in java, Automatic garbage collection


• C# has explicit heap-dynamic, stack-dynamic objects, all implicitly deallocated

• Advantage: dynamic storage management like link list to grow/shrink


• Disadvantage: inefficient, costly, complex and unreliable due to pointers
Storage Binding - 4. Implicit heap-dynamic
• Allocation and deallocation caused by assignment statements
– bound to heap storage only when assigned values
– all their attributes bound every time they are assigned

e.g.
all variables in APL
in JavaScript assignment statement: highs = [74, 84, 86, 90, 71];

• Regardless of whether variable named highs was previously used in program or


what it was used for, it is now array of five numeric values (Associated Arrays).

Advantage:
• highest degree of flexibility, allowing highly generic code to be written

Disadvantages:
• - Inefficient, run-time overhead because all attributes are dynamic
• - Loss of error detection
Type Checking
• Activity of ensuring that operands of an operator are of compatible types

• Compatible type is legal for operator, allowed under language rules to be implicitly
converted, by compiler- generated code, to legal type.
– This automatic conversion is called a coercion.

• If int variable, float variable added in Java, value of int variable coerced to float
and floating-point add done.

• Generalize Subprograms as operators whose operands are their parameters.


• Assignment symbol as binary operator, with target variable and expression being
operands.

• Type error is application of an operator to operand of inappropriate type.


• In original version of C, if int value passed to function that expected float value,
type error would occur (compiler didn’t check parameters type)

• If all type bindings of variables are static in a lang, nearly all type checking can be
static.
• If type bindings are dynamic, type checking must be dynamic
Strong Typing and Coercion
• Programming language is strongly typed if type errors always detected at compile
time or at run time.
– Otherwise it is weakly typed.
• Ability of compiler to detect all misuses of variables that result in type errors.

1. FORTRAN 77 is not
2. Pascal is not: variant records
3. Modula-2 is not: variant records, WORD type
4. C/C++ not: parameter type checking can be avoided; unions not type checked.
5. Ada is, almost (UNCHECKED CONVERSION is loophole), (Java , C# similar to
Ada to explicitly cast, no implicit ways type errors can go undetected.)

• Coercion rules strongly affect strong typing error detection


– C++ is less reliable due to high coercion than Ada that has less coercion,
– ML and F# has no coercion
Dynamic Type Binding
Advantages:
1. Flexibility
2. More short cuts and tricks possible

Disadvantages:
3. efficiency
4. run-time error detection (costs more)
5. Readability affected.
• Type checking is complicated when language allows
memory location to store values of different types at
different times during execution.

• Such memory locations can be created with Ada


variant records, C and C++ unions.

• So type checking, must be dynamic and requires run-


time system to maintain type of current value of such
memory locations.

• So, even though all variables statically bound to types


in languages such as C++, not all type errors can be
detected by static type checking.
Type Compatibility

• Compatibility rules dictate types of operands acceptable for each of operators


– thereby specify possible type errors of language.
• Operand type can be implicitly converted by compiler or run-time system to make it
acceptable to operator.

• Simple Rules for scalar types, complex for arrays, structures, user defined types (or
classes)

• Coercion of these types rare, so issue is not type compatibility, but type
equivalence.
– i.e., two types equivalent if operand of one type in expression substituted for
one of other type, without coercion.

• Type equivalence is strict form of type compatibility – i.e compatibility without


coercion.
Compatibility by Name
• Two variables have compatible types if they are in either same
declaration or in declarations that use same type name
Int x, y; int x; int y;
- Easy to implement but highly restrictive:
- Subranges of integer types not compatible with integer types as in Ada
count and index are not equal

type Indextype is 1..100;


count : Integer;
index : Indextype;

- Formal parameters must be same type as their corresponding actual


parameters,
user-defined type must be declared globally (Pascal)
Compatibility by Structure
Two variables have compatible types if their types have identical structures
- More flexible, but harder to implement (entire structure must be compared)

Some Issues
- How to compare a data structure that refers to its own type e.g. a link list

- Are two record types compatible if they are structurally the same but use
different field names? Struct A { int x, float y, char n; } struct B{ int y, float
z, char No}

- Are two array types compatible if they are the same except that the subscripts
are different? (e.g. [1..10] and [-5..4])

- Are two enumeration types compatible if their components are spelled differently?
E.g. sat, sun, mon vs. Saturday, Sunday, Monday

- With structural type compatibility, you cannot differentiate between types of the
same structure (e.g. celsius and fahrenheit, both float, can be mixed in
expressions, although have different abstractions of same domain)
Type Compatibility in Ada
restricted form of name type equivalence,

A derived type is new type that is based on some previously defined type with which
it is not equivalent, (may have identical structure).
Derived types inherit all properties of their parent types. E.g.

type Celsius is new Float; temp1:clecius temp2:fahrenhiet


type Fahrenheit is new Float;
Type pressure is new Float; p1:pressure

The types of variables of these two derived types are not equivalent, although their
structures are identical. Furthermore, variables of both types are not type equivalent
with any other floating-point type.

A subtype is range-constrained version of an existing type. type equivalent with its


parent type.

type Derived_Small_Int is new Integer range 1..100;


subtype Subrange_Small_Int is Integer range 1..100;
Type Compatibility in C/C++
Uses both name and structure type equivalence.
Every struct, enum, and union declaration creates a new type
(name type equivqlence).
One exception in C: if two struct, enum, or unions defined in different files, in which
case structural type equivalence is used.
C++ is like C except there is no exception for struct and unions defined in different
files. Int x, y, z; int w; float yy;
Int A[10]; int B[10];
Other nonscalar types use structure type equivalence.
Array types are equivalent if they have same type components. Also, if array type has
constant size, it is equivalent either to other arrays with same constant size or to
with those without a constant size.
Typedef simply defines new name for existing type. So, any type defined with typedef
is type equivalent to its parent type.
Struct Stack{int TopStack; int Data[100]; } X, Y; int x, y;
Struct Set{int NumberInSet; int Data[100]; } A, B;
How to calculate Stack equality of X, Y and set equality of A, B?
Attributes of Variables - 6. Scope

Range of statements over which a variable is visible

Nonlocal variables of program unit are visible but not


declared there.

Scoping rules of language determine how references


to names associated with variables?
Static Scope
- Based on program text location (spatial)

- named because scope of variable can be statically determined


before execution.

- To connect name reference to variable, you (or compiler) must


find declaration. Int A (){ int x=1; int B(){ cout<< x;} }

- Search process:
search declarations, first locally, then in increasingly larger
enclosing scopes, until one is found for given name

- Enclosing static scopes (to a specific scope) called its static


ancestors; nearest static ancestor called a static parent
Variables can be hidden from function/block by having a "closer"
variable with same name.

- C++ and Ada allow access to these "hidden" variables

Blocks - method of creating static scopes inside program units


- introduced by ALGOL 60

Examples:
C/C++: for (...) {
int index= 5;
if( ){
int index=1;
index++;
}
...
}
Ada: declare INDEX : INTEGER;
1 int main()
2 { Evaluation of Static Scoping
3 int a = 1;
4 A(); Main() calls A() and B(),
5 B(); A() calls C() and D() whereas
6 …} B() calls E().

7 int A() // Functions on same level can call


global
each other.
8 {
9 C();
All variables declared in main()
10 D(); … }
are visible to all functions.
11 int B() //
global
12 { … E(); …
}
1 int main()
Suppose specs changed so that D()
2 {
must now access some data in B()
3 int a = 1; int
c; Solutions:
4 A(); 1. Put D() in B() (but then C() can no
5 B(); longer call it, because it is local to
6 …} B() and D() cannot access A()'s
variables)
7 int A() //
global 2. Move data from B() that D() needs
8 { int b = 2; to main() (but then all procedures
9 C(); can access them)
10 D(); … }
11 int B() // Same problem for procedure access!
global Disadvantage: static scoping often
12 { int c; int encourages many globals.
D() { cout<<c;} //
Dynamic Scope

Based on calling sequences of program units, and


not on their textual layout (temporal versus spatial).

References to variables connected to declarations by


searching back through chain of subprogram calls that
forced execution to this point.
1 main() Scope- Example
2 {
3 int x = 1;
Main() calls A()
int y=2;
4 A () calls B()
5 A(); B() uses x defined in A()
6 B();
7 } Main() calls B()
B() uses x defined in main()
8 A()
9 { int x = 2;
10 … In Static scoping
11 B(); …} reference to main()’s x
vs.
12 B() In Dynamic scoping
13 { …int bb; reference to A()'s x
14 cout << x;
Evaluation of Dynamic Scoping

- Advantage: convenience main(){ A();}


- Disadvantage: poor readability int A(){
- static int
x=1;
- int B(){
- x++;
- }
- return;
- }

Scope and lifetime are sometimes closely related,


but are different concepts!!
Referencing Environments
Referencing environment of statement is collection of all names that are
visible in statement.

e.g. in C++: using namespace. A() { int aa;} int B(){ int bb;
cout<<aa;} C(){ int cc; cout<<bb<<aa<<cc;}

In static scoped language, referencing environment is local variables


plus all visible variables in all enclosing scopes.
A(){ int x=1; B(); } int B(){ int y =2; cout<<x<<y; C();} int C(){
int z= 1; cout<< x<< y<z; }
A subprogram is active if its execution has begun but has not yet
terminated.

In dynamic-scoped language, referencing environment is local variables


plus all visible variables in all active subprograms.
Named Constant
Constant: A variable that is bound to a value only when it is bound to storage.

Advantages: readability and modifiability

The binding of values to named constants can be either static (called manifest
constants) or dynamic.

Examples in Languages:
Pascal: literals only
Modula-2 and FORTRAN 90: constant-valued expressions
Ada, C++, and Java: expressions of any kind

Variable Initialization
The binding of a variable to a value at time it is bound to storage.
Initialization is often done on declaration statement.
e.g.,
Ada: SUM : FLOAT := 0.0;
C++: int index = 0;

You might also like