Open In App

Type Checking in Compiler Design

Last Updated : 27 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Type checking is the process of verifying and enforcing constraints of types in values. A compiler must check that the source program should follow the syntactic and semantic conventions of the source language and it should also check the type rules of the language. It allows the programmer to limit what types may be used in certain circumstances and assigns types to values. The type-checker determines whether these values are used appropriately or not.

It checks the type of objects and reports a type error in the case of a violation, and incorrect types are corrected. Whatever the compiler we use, while it is compiling the program, it has to follow the type rules of the language. Every language has its own set of type rules for the language. We know that the information about data types is maintained and computed by the compiler.

The information about data types like INTEGER, FLOAT, CHARACTER, and all the other data types is maintained and computed by the compiler. The compiler contains modules, where the type checker is a module of a compiler and its task is type checking.

Conversion

Conversion from one type to another type is known as implicit if it is to be done automatically by the compiler. Implicit type conversions are also called Coercion and coercion is limited in many languages.

Example: An integer may be converted to a real but real is not converted to an integer.

Conversion is said to be Explicit if the programmer writes something to do the Conversion.

Tasks:

  1. has to allow “Indexing is only on an array” 
  2. has to check the range of data types used
  3. INTEGER (int) has a range of -32,768 to +32767
  4. FLOAT has a range of 1.2E-38 to 3.4E+38. 

Types of Type Checking:

There are two kinds of type checking:

  1. Static Type Checking.
  2. Dynamic Type Checking.

Static Type Checking:

Static type checking is defined as type checking performed at compile time. It checks the type variables at compile-time, which means the type of the variable is known at the compile time. It generally examines the program text during the translation of the program. Using the type rules of a system, a compiler can infer from the source text that a function (fun) will be applied to an operand (a) of the right type each time the expression fun(a) is evaluated.

Examples of Static checks include:

  • Type-checks: A compiler should report an error if an operator is applied to an incompatible operand. For example, if an array variable and function variable are added together.
  • The flow of control checks: Statements that cause the flow of control to leave a construct must have someplace to which to transfer the flow of control. For example, a break statement in C causes control to leave the smallest enclosing while, for, or switch statement, an error occurs if such an enclosing statement does not exist.
  • Uniqueness checks: There are situations in which an object must be defined only once. For example, in Pascal an identifier must be declared uniquely, labels in a case statement must be distinct, and else a statement in a scalar type may not be represented.
  • Name-related checks: Sometimes the same name may appear two or more times. For example in Ada, a loop may have a name that appears at the beginning and end of the construct. The compiler must check that the same name is used at both places.

The Benefits of Static Type Checking:

  1. Runtime Error Protection.
  2. It catches syntactic errors like spurious words or extra punctuation.
  3. It catches wrong names like Math and Predefined Naming.
  4. Detects incorrect argument types.
  5. It catches the wrong number of arguments.
  6. It catches wrong return types, like return “70”, from a function that’s declared to return an int.

Dynamic Type Checking:

Dynamic Type Checking is defined as the type checking being done at run time. In Dynamic Type Checking, types are associated with values, not variables. Implementations of dynamically type-checked languages runtime objects are generally associated with each other through a type tag, which is a reference to a type containing its type information. Dynamic typing is more flexible. A static type system always restricts what can be conveniently expressed. Dynamic typing results in more compact programs since it is more flexible and does not require types to be spelled out. Programming with a static type system often requires more design and implementation effort.

Languages like Pascal and C have static type checking. Type checking is used to check the correctness of the program before its execution. The main purpose of type-checking is to check the correctness and data type assignments and type-casting of the data types, whether it is syntactically correct or not before their execution.
Static Type-Checking is also used to determine the amount of memory needed to store the variable.

The design of the type-checker depends on:

  1. Syntactic Structure of language constructs.
  2. The Expressions of languages.
  3. The rules for assigning types to constructs (semantic rules).
     

The Position of the Type checker in the Compiler:

Type checking in Compiler

The token streams from the lexical analyzer are passed to the PARSER. The PARSER will generate a syntax tree. When a program (source code) is converted into a syntax tree, the type-checker plays a Crucial Role. So, by seeing the syntax tree, you can tell whether each data type is handling the correct variable or not. The Type-Checker will check and if any modifications are present, then it will modify. It produces a syntax tree, and after that, INTERMEDIATE CODE Generation is done. 

Overloading:

An Overloading symbol is one that has different operations depending on its context.

Overloading is of two types:

  1. Operator Overloading 
  2. Function Overloading

Operator Overloading: In Mathematics, the arithmetic expression “x+y” has the addition operator ‘+’ is overloaded because ‘+’ in “x+y” have different operators when ‘x’ and ‘y’ are integers, complex numbers, reals, and Matrices.

Example: In Ada, the parentheses ‘()’ are overloaded, the ith element of the expression A(i) of an Array A has a different meaning such as a ‘call to function ‘A’ with argument ‘i’ or an explicit conversion of expression i to type ‘A’. In most languages the arithmetic operators are overloaded.

Function Overloading: The Type Checker resolves the Function Overloading based on types of arguments and Numbers.

Example: 

E-->E1(E2)
               {
                  E.type:= if E2.type = s 
                  E1.type = s -->t then t
                                 else type_error 
               }

Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads