0% found this document useful (0 votes)
187 views9 pages

Compiler Ch6 (Part 1)

A type system assigns type expressions to parts of a program. Type checking involves checking that operations are applied to operands of compatible types based on these type expressions. It can be done statically during compilation or dynamically at runtime. Static type checking eliminates runtime type errors.

Uploaded by

api-3712520
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
187 views9 pages

Compiler Ch6 (Part 1)

A type system assigns type expressions to parts of a program. Type checking involves checking that operations are applied to operands of compatible types based on these type expressions. It can be done statically during compilation or dynamically at runtime. Static type checking eliminates runtime type errors.

Uploaded by

api-3712520
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 9

Type Checking

Dewan Tanvir Ahmed


Assistant Professor, CSE
BUET
Type Checking
• A compiler has to do semantic checks in addition to syntactic checks.
• Semantic Checks
– Static – done during compilation
– Dynamic – done during run-time
• Type checking is one of these static checking operations.
– we may not do all type checking at compile-time.
– Some systems also use dynamic type checking too.
• 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
– In practice, some of type checking operations are done at run-time (so, most of the programming
languages are not strongly-typed).
– Ex: int x[100]; … x[i]  most of the compilers cannot guarantee that i will be between 0 and 99
Static Type Checking

Static checking examples:


 Type checks.
Report an error if an operator is applied to an incompatible operand
 Flow-of-control checks.
Statements that causes flow of control to leave a construct must have
some
 place to which to transfer the flow of control
 Uniqueness checks.
There are situations where an object must be defined exactly once.
 labels, identifiers
 Name-related checks.
Sometimes the same names may be appeared two or more times.
 Beginning and end of a construct
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)
Type Expression
• 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.
– Function f(a,b: integer) : ↑ integer
» Integer × integer → pointer(integer)

• Records: The record type constructor will be applied to a tuple formed from field
names and field types.
Type row = record
address : integer;
lexeme: array[1..15] of char
end;

Var table: array[1..101] of row;

Declares the type name row representing the type expression


record( (address × integer) × (lexeme × array(1..15,char) )
A Simple Type Checking System

P → D;E
D → D;D
D → id:T { addtype(id.entry,T.type) }
T → char { T.type=char }
T → int { T.type=int }
T → real { T.type=real }
T → ↑T1 { T.type=pointer(T1.type) }
T → array[intnum] of T1
{ T.type=array(1..intnum.val,T1.type) }

Parts of translation scheme that saves the


type of an identifier
Type Checking of Expressions
E → id { E.type=lookup(id.entry) }

E → literal { E.type=char }

E → intliteral { E.type=int }

E → realliteral { E.type=real }

E → E1 + E2 { if (E1.type=int and E2.type=int) then E.type=int


else if (E1.type=int and E2.type=real) then E.type=real
else if (E1.type=real and E2.type=int) then E.type=real
else if (E1.type=real and E2.type=real) then E.type=real
else E.type=type-error }

E → E1 [E2] { if (E2.type=int and E1.type=array(s,t)) then E.type=t


else E.type=type-error }

E → E1 ↑ { if (E1.type=pointer(t)) then E.type=t


else E.type=type-error }
Type Checking of Statements

S → id = E { if (id.type=E.type then S.type=void


else S.type=type-error }

S → if E then S1 { if (E.type=boolean then S.type=S1.type


else S.type=type-error }

S → while E do S1 { if (E.type=boolean then S.type=S1.type


else S.type=type-error }
Type Checking of Functions
E → E1 ( E2 ) { if (E2.type=s and E1.type=s→t) then E.type=t
else E.type=type-error }

Ex: int f(double x, char y) { ... }

f: double x char → int

argument types return type

function root (function f(real):real; x : real) : real

Root: (real → real) × real → real

You might also like