- By
**chipo** - Follow User

- 93 Views
- Uploaded on

Download Presentation
## Type Checking

**An Image/Link below is provided (as is) to download presentation**

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript

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

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;

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

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

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

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

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 */

};

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.

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

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 boolean;

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));

Two-pass type resolution

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

procedure analyze_indexed_component (N : Node_Id) is

begin

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;

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

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

Polymorphic functions

- fun len lis = if lis = nullthen 0 else 1 + len (tl lis)
- Len : α list -> int
- fun map (f lis) =

if L = null then nullelse 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.

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)

Download Presentation

Connecting to Server..