Type checking is basically the enforcement of a set of rules
designed to ensure that only valid operands are provided to
the various operations that can be invoked within a program.
Type systems are a big topic in programming language
design but typically are given little attention in
compiler courses and textbooks.
The specification of a type system requires:
a language/notation for describing types.
a set of rules specifying how to associated
type descriptions with language constructs
(primarily expressions).
a set of rules specifying restrictions on the
types associated with expressions appearing in
various contexts.
The description of types in "conventional" languages typically
includes:
A set of names for primitive types (int, bool, etc.),
Constructors for composite types including:
pointer( t )
array( i, t )
record constructor ( id1:t1, id2:t2, ... )
product constructor ( t1 x t2 x . . . tn )
function constructor ( t1 -> t2 )
The ability to bind and use type names.
Essential for the description of list, trees and
other recursive types.
The rules for associating types with expression are typically
inextricably intermixed with the rules specifying type constraints.
Basically, if a expression violates the constraints, none of the rules
for assigning types will apply.
For example....
Given an expression, e, of the form:
x + y
where x and y have type "int" then the type of 'e'
is "int".
Given an expression, e, of the form:
f(x)
where f has type t1 rightarrow t2 and x has type t1
then e has type t2.