Slides 08 Programming Languages - UET CS - Talha Waheed - Names Bindings Type Checking and Scope
Slides 08 Programming Languages - UET CS - Talha Waheed - Names Bindings Type Checking and Scope
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
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?)
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
Aliases
- If two variable names can be used to access same memory location, they
are called aliases
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
Vs.
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
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.)
• 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.
e.g.
all variables in APL
in JavaScript assignment statement: highs = [74, 84, 86, 90, 71];
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.
• 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.)
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.
• 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.
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.
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.
- Search process:
search declarations, first locally, then in increasingly larger
enclosing scopes, until one is found for given name
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().
e.g. in C++: using namespace. A() { int aa;} int B(){ int bb;
cout<<aa;} C(){ int cc; cout<<bb<<aa<<cc;}
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;