Sunday, September 27, 2009

Principles of Programming Languages - Module 4

Module 4  
Names, Bindings, Type Checking and Scopes

Names

One of the fundamental attributes of variables is names, which have broader use than simply for variables.  They are also associated with labels, subprograms, formal parameters, and other program constructs.  The term identifier is often used interchangeably with name.

Name forms

A name is a string of characters used to identify some entity in a program.  The earliest programming languages used single-character names.  This was natural because early programming was primarily mathematical, and mathematicians have long used single-character names for unknowns in their formal notations.

A programming language has a maximum length of a name. For example, FORTRAN 90 and C allow up to 31 characters. Ada names have no length limit.  Some languages like C++, do not specify a length limit on names.

The commonly acceptable name form is a string with a reasonably long length limit, if any, with some connector character such as the underscore(_) included.  The underscore serves the same purpose as a space in English text but without terminating the name string in which it is placed.

In some languages, like C, C++, and Java, uppercase and lowercase letters in names are distinct; that is, names in these languages are case sensitive.

Special Words

Special words in programming languages are used to make programs more readable by naming actions to be performed.  They are  used to separate the syntactic entities of programs.  In most languages, these words are classified as reserved words, but in some they are only keywords.

A keyword is a word of a programming language that is special only in certain contexts.  A reserved word is a special word  of a programming language that cannot be used as a name.  As a language design choice, reserved words are better than keywords because the ability to redefine keywords can lead to readability problems.

Variables

A program variable is an abstraction of a computer memory cell or collection of cells.  Programmers often think of variables as names for memory locations, but there is much more to a variable than just a name.  A variable can be characterized as a sextuple of attributes: (name, address, value, type, lifetime, scope).
Address

The address of a variable is the memory address with which it is associated.  It is sometimes called its l-value, because that is what is required when a variable appears in the left side of an assignment statement.

Aliases

It is possible to have multiple identifiers reference the same address.  When more than one variable name can be used to access a single memory location, the names are called aliases.  Aliasing is a hindrance to readability because it allows  a variable to have its value changed by an assignment to a different variable.

Type

The type of a variable determines the range of values the variable can have and the set of operations that are defined for values of the type.

Value

The value of a variable is the contents of the memory cell or cells associated with the variable.  It is convenient to think of computer memory in terms of abstract cells, rather than physical cells.  It is sometimes called the variable's r-value because it is what is required when the variable is used on the right side of an assignment statement.


Bindings

Binding is an association such as between an attribute and an entity or between an operation and a symbol.  The time at which a binding takes place is called binding time. Bindings can take place at language design time, language implementation time, compile time, link time, load time, or load time. 

Examples:
• The asterisk symbol(*) is usually bound to the multiplication operation at language design time.
• A variable in C or C++ program is bound to as particular data type at compile time.
• A variable may be bound to a storage cell when the program is loaded to the memory
• A call to a library subprogram is bound to the subprogram code at link time.

Given some lines of a C++ program:

int iCt;

iCt = iCt + 1;

Some of the bindings and their binding times for the parts of this assignment statement are as follows:
• Set of possible types for iCt:  bound at language design time.
• Type of count:  bound at compile time.
• Set of possible values of iCt: bound at compiler design time.
• Value of iCt: bound at execution time with this statement.
• Set of possible meanings for the operator symbol +:  bound at language definition time.
• Meaning of the operator symbol + in this statement:  bound at compile time.
• Internal representation of the literal 1:  bound at compiler design time.

A binding is static if it occurs before run time and remains unchanged throughout program execution.  If it occurs during run time or can change in the program execution, it is called dynamic.

Type Bindings

Before a variable can be referenced in a program, it must be bound to a data type.  The two important aspects of this binding are (1) how the type is specified and (2) when the binding takes place.

Forms of Variable Declaration
1. Explicit declaration - a statement in a program that lists variable names and specifies that they are a particular type.
2. Implicit declaration - a means of associating variables with types  through default conventions instead of declaration statements.

The first appearance of a variable name in a program constitutes its implicit declaration.  Both explicit and implicit declarations create static binding to types.

Dynamic Type Binding

With dynamic type binding, the type is not specified by a declaration statement.  Instead, the variable is bound to a type when it is assigned a value in an assignment statement. When the assignment statement is executed, the variable being assigned is bound to the type of the value, variable, or expression on the right side of the assignment.

One of its advantages is that it provides a great deal of programming flexibility.  With dynamic type binding, one can deal with data of any type.

Dynamic type binding has also disadvantages. One of these is the error detection capability of the compiler is diminished relative to a compiler for a language with  static type bindings, because any two types can appear on opposite sides of the assignment operator.  Incorrect types of right sides of assignments are not detected as errors; rather, the type of the left side is simply changed to the incorrect type.

Type Inference

For programming languages like ML, Miranda, and Haskell, with type inference, the types of most expressions can be determined without requiring the programmer to specify the types of the variables

Type Checking

When dealing with type checking, one has to consider the following:
1. Subprograms will be taken as operators whose operands are their parameters;
2. The assignment symbol will be thought of  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 compiler-generated code to a legal type which is known as coercion.  A type error is the application of an operator to an operand of an inappropriate type.

Strong Typing

This is one of the new ideas in language design that became prominent in the so-called structured programming revolution of the 1970s. A strongly typed language is one in which each name in a program in the language has a single type associated with it, and that type is known at compile time.  A programming language is considered strongly typed if type errors are always detected.  The importance of strong typing lies in its ability to detect all misuses of variables that result in type errors.  Languages like FORTRAN, C and C++ are not strongly typed.  Examples of programming languages that are nearly strongly typed are Pascal and Ada.  Languages like ML and Java are strongly typed.

Type Compatibility

The design of the type compatibility rules of a language is important, because it influences the design of the data types and operations provided for values  of those types.

Two different type compatibility methods:
1. Name compatibility -  this means that two variables have compatible types only if they are  in either the same declaration or in declarations that use the same type name.
2. Structure compatibility - this means that two variables have compatible types if their types have identical structures.

Scope

One of the most important factors having an effect on the understanding of variables is scope.  The scope of a program variable is defined as the range of statements in which the variable is visible.  A variable is visible in a statement if it can be referenced in that statement  A variable is local in a program unit or block if it is declared there.  The nonlocal variables of a program unit or block are those that are visible within the program unit or block but are not declared there. (Sebesta)

No comments:

Post a Comment

Related Posts with Thumbnails