Software and Systems Engineering Standards: Verification and Validation of Sy...
Type Checking
1. Type Checking
Type checking is the process of verifying that each operation executed in a program respects the type
system of the language. This generally means that all operands in any expression are of appropriate types
and number. Much of what we do in the semantic analysis phase is type checking.
Two Types of Type Checking
Static Type Checking
Dynamic Type Checking
Static Checking
Refers to the compile-time checking of programs in order to ensure that the semantic conditions of the
language are being followed. Examples of static checks include:
Type checks
Flow-of-control checks
Uniqueness checks
Name-related checks
Type checks: A compiler should report an error if an operator is applied to an incompatible operand.
Example- if an array variable and function variable are added together.
Flow-of-control checks: statements that cause flow of control to leave a construct must have some place
where control can be transferred. Example- an error occurs when an enclosing statement, such as break,
does not exist in the switch statement.
Uniqueness checks: a language may dictate that in some contexts, an entity can be defined exactly once;
e.g., identifier declarations, labels, values in case expressions.
Name-related checks: Sometimes the same name must appear two or more times;
e.g., in Ada a loop or block can have a name that must then appear both at the beginning and at the end
Dynamic type checking
Implemented by including type information for each data location at runtime.
Dynamic checking can catch:
illegal argument values. For example, the integer expression x/y is only erroneous when y is
actually zero; otherwise it works. So in this expression, divide-by-zero is not a static error, but a
dynamic error.
unrepresentable return values, i.e., when the specific return value can’t be represented in the type.
out-of-range indexes, e.g., using a negative or too-large index on a string.
Type System
• A type system is a collection of rules for assigning type expressions to the parts of a program.
• A type checker implements a type system.
• A sound type system eliminates run-time type checking for type errors.
• A programming language is strongly-typed, if every program its compiler accepts will execute
without type errors.
2. Type Expression
• The type of a language construct is denoted by a type expression.
• A type expression can be:
– A basic type
• a primitive data type such as integer, real, char, boolean, …
• type - error to signal a type error
• void : no type
– A type name
• a name can be used to denote a type expression.
– A type constructor applies to other type expressions.
• arrays: If T is a type expression, then array(I,T) is a type expression where I
denotes index range. Ex: array(0..99,int)
• products: If T1 and T2 are type expressions, then their cartesian product T1 x T2
is a type expression. Ex: int x int
• pointers: If T is a type expression, then pointer(T) is a type expression. Ex:
pointer(int)
• functions: We may treat functions in a programming language as mapping from a
domain type D to a range type R. So, the type of a function can be denoted by the
type expression D→R where D are R type expressions. Ex: int→int represents
the type of a function which takes an int value as parameter, and its return type is
also int.
Type conversion
Type conversion or typecasting refers to changing an entity of one datatype into another. There are two
types of conversion: implicit and explicit.
Conversion from one type to another is said to be implicit if it is done automatically by the compiler. Implicit
type conversions, also called coercions.
Conversion is said to be explicit if the programmer must write something to cause the conversion. Explicit
conversions are also called casts.