1 / 16

Type Checking

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;

ezra
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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Type Checking Legality checks Operator determination Overload resolution

  2. 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

  3. 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;

  4. 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

  5. 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

  6. 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

  7. 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

  8. 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 */ };

  9. 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.

  10. 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

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

  12. 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;

  13. 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

  14. 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

  15. 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.

  16. 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)

More Related