16
Type Checking Legality checks Operator determination Overload resolution

Type Checking

Embed Size (px)

DESCRIPTION

Type Checking. Legality checks Operator determination Overload resolution. Type as a synthesized attribute. Expr ::= Expr + Term if Etype (Expr 2 ) = Etype (Term) then Etype (Expr 1 ) := Etype (Expr 2 ); else Etype (Expr1) = Any_Type; - PowerPoint PPT Presentation

Citation preview

Page 1: Type Checking

Type Checking

Legality checksOperator determinationOverload resolution

Page 2: Type Checking

Type as a synthesized attribute

Expr ::= Expr + Term

if Etype (Expr2) = Etype (Term) then

Etype (Expr1) := Etype (Expr2);

else

Etype (Expr1) = Any_Type;

Error (“incompatible types for +”, Expr1);

end if; Sufficient for Pascal and C

Page 3: Type Checking

Rules for operations on composite types

Indexed_Component ::= Prefix ( Expr )

A_Typ := Etype (Prefix);

Etype (Indexed_Component) := Any_Type; - - by default

if not Is_Array_Type (A_Typ) then

Error (“expect array type in indexed component”, Prefix);

elsif Etype (Expr) /= Index_Type (A_Typ) then

Error (“wrong index type”, Expr);

else

Etype (Indexed_Component) := Component_Type (A_Typ);

end if;

Page 4: Type Checking

Type expressions

Built from: Primitive types: boolean, float, integer Type constructors: array, record, access, function

Type_Expr ::= Prim_Type Type_Expr ::= Type_Name Type_Expr ::= array (Type_Expr) Type_Expr

Pascal, Ada : index type is part of type expression Early Pascal : index bounds are part of type expression (bad idea)

Type_Expr ::= record (…) Type_Expr ::= access Type_Expr Type checking is a set of rules to compute the type expressions of

all expressions in the program

Page 5: Type Checking

Product types and functions

Type_Expr := Type_Expr * Type_Expr Intuitively, a pair of types

Type_Expr := Type_Expr1 -> Type_Expr2

A function that takes an argument of type Type_Expr1 and returns a value of type Type_Expr2

function Distance (C1, C2 : Character) return Integer; Distance: character * character -> integer real merge (int[] a, int[]b); merge: array ( int ) * array ( int ) -> real

Page 6: Type Checking

Type checking and type equivalence

Type correctness can be stated in terms of equivalence of type expressions:

int [ ] arr1; // arr2 : array ( int )

int [ ] arr2; // arr2 : array ( int )

Arr1 = arr2;

// ok in Java: type expressions are equivalent

Usually the rule in languages where a declaration can contain an arbitrary type expression

Page 7: Type Checking

Type checking and name equivalence

Arr1 : array (1..10) of integer;

Arr2 : array (1..10) of integer;

Arr1 := Arr2; // illegal in Ada: different anonymous types.

-- same as:

type anon1 is array (1..10) of integer;

Arr1 : anon1; -- Arr1 : anon1

type anon2 is array (1..10) of integer;

Arr2 : anon2: -- Arr2 : anon2

-- Arr1 and Arr2 are not equivalent.

Language does not allow arbitrary (anonymous) type expressions in a declaration

Page 8: Type Checking

Type expressions with cycles

type t1 = record c: integer; p: pointer (t1); end record;type t2 = record c: integer; p: pointer (t2); end record;

t1 and t2 are equivalent in Algol68

C approach: name of type is part of type expression, types are not equivalent:

struct cell { int c; struct cell *next;

/* struct cell is in type expression */};

Page 9: Type Checking

Type checking and coercions

If language allows coercions, type depends on context, cannot be purely synthesized.

For C++ boolean operators (Stroustrup C.6.3) If either operand is of type long double, the other is

converted to long double Otherwise, if either operand is double, the other is

converted to double Otherwise, if either is float, the other is converted to float Otherwise, integral promotions are performed on both:

char, (un) signed_char, (unsigned) short int -> int bit-field -> int bool -> int

Further complication: user-defined conversions.

Page 10: Type Checking

Overload resolution If expression is overloaded, collect set of possible

meanings sm. If context is overloaded, collect set of possible context

types sc. Expression is legal in context if intersection of sc and sm

is a singleton: | sc ∩ sm | = 1

C++: if multiple interpretations, select the one with smallest number of coercions

Ada: if multiple interpretations, select predefined numeric operator over user-defined one

Page 11: Type Checking

Overloaded context: procedure call

procedure P (x : integer; y : float);

procedure P (x : float; y : float);

procedure P (x : boolean; z : integer);

function F (x : integer) return integer;

function F (x : float) return integer;

function F (x : integer) return float;

function F (x : float) return boolean;

P (f (3.14), f (1)); -- P1 (f2 (3.14), f3 (1));

Page 12: Type Checking

Two-pass type resolution

Bottom-up (analyze) : synthesize candidate types Top-down (resolve): propagate unique context type

procedure analyze_indexed_component (N : Node_Id) isbegin

analyze prefix, collect set of interpretations Pre analyze index, collect set of interpretations Ind forall t in Pre loop if there is a compatible ix in Ind then

add component_Type (t) to interpretations of N else remove t from Pre; end if;

end loop; end;

Page 13: Type Checking

Two-pass type resolution (2)

procedure resolve_indexed_component (N : Node_Id; Typ : Entity_Id)

is

begin

find unique interpretation of prefix whose component type is Typ

resolve index using this interpretation

end;

General scheme:

bottom-up: analyze descendants, synthesize local attribute

top-down : disambiguate construct, propagate to descendants

Page 14: Type Checking

Type variables and polymorphism

In a language with list primitives (LISP, ML) what is the type expression that describes CAR or hd?

Informally, given a list of components of any kind, CAR yields a value of that kind:

Car : list_of_whatever -> whatever

A type variable is universally quantified: the expression is valid for any instantiation of the variable. In ML notation: Head (hd) α list -> α Tail (tl) α list -> α list Constructor (::) : α * α list -> α list

Page 15: Type Checking

Polymorphic functions

fun len lis = if lis = null then 0 else 1 + len (tl lis) Len : α list -> int

fun map (f lis) =

if L = null then null else f (hd lis) :: map (f (tl lis))

Map: (α ->β) * α list -> β list

Map applies a function to each element of a list. The result type of the function is not necessarily equal to the element type of the list.

Page 16: Type Checking

The limits of type inference

Overloading must be handled specially Self-application is not typable:

1 + g (g)

g is a function: g: α -> β

g applied to itself yields an integer: β = int α = α -> β : circular definition (not unifiable)