Type Equivalence An Equivalence relation is a reflexive








- Slides: 8
Type Equivalence • An Equivalence relation is a reflexive, symmetric, transitive relation, (a. Ra, a. Rb and b. Rc iff c. Ra). • An Equivalence relation forms a partition of a set into one or more disjoint equivalence classes. If two elements belong to the same class, they are said to be equivalent. • There are many different notions of type equivalence Lecture #21 PLP Spring 2004, UF CISE 1
Structural Equivalence • Under this notion of equivalence, two variables have the same type (are type equivalent) if the underlying structural representation of their types is identical. Clearly all primitive types are identical to themselves. What about structured types: struct Rec 1 { char x; int y; char z[10]; }; • But what constitutes structure – types of constituent elements – names of constituent elements? – order of constituent elements? • If the elements are of structured type, apply the matching algorithm recursively. • If the type definitions are recursive, start by assuming that all types are equivalence unless it can be shown that they aren’t. Lecture #21 PLP Spring 2004, UF CISE 2
More Structural Equivalence Questions • How much of an array’s type represents its structure? int A 1[10]; int A 2[20]; • These may be type equivalent in some languages and different in others. Lecture #21 PLP Spring 2004, UF CISE 3
Name Equivalence • Two variables are considered to be equivalent if their types have the same name. • In its strictest form, name equivalence is easy to implement. Just check to see if type names are the same. Anonymous type names, like those of d and e struct { char x; int y; } d; struct { char x; int y; } e; are considered to be different, but d and e woule be considered to have the same type in this declaration: struct { char x; int y; } d, e; • Ada even allows one to draw distinctions between existing types and new names for them: type Age is new integer; // creates a new type name subtype Age is integer; // creates a type name alias Lecture #21 PLP Spring 2004, UF CISE 4
What do Languages Really Use? • C – – Name equivalence for structs and unions structural equivalence for everything else. typedefs create equivalent type name alias Array lengths play no role in equivalence • Pascal – Name equivalence for most elements – New type names are still equivalent • Java – Name equivalence for classes and interfaces – Structural equivalence for arrays • ML – datatype constructs a new nonequivalent type – type constructs an equivalent type name alias Lecture #21 PLP Spring 2004, UF CISE 5
Type Checking • Type checking is the process of verifying that the types of all program operands of are consistent with their operations. • Can happen at compile time (static) and/or at run time (dynamic). – C: does all checking it will do at compile time (but doesn’t enforce equivalence everywhere) – Scheme: does all checking at run time (but makes sure everything really matches) – Ada: Does all statically performable checking at compile time, but also provides run-time error checks for bounds constraints, etc. • Type inference is the process of determining the type of an expression from its operation and operands. • Many languages like C require static declaration of variable types, primarily to make type checking and type inference easier. But static declarations are not required in order to do this in many cases. ML and Haskell perform static type checking but don’t require types of variables to be declared. Lecture #21 PLP Spring 2004, UF CISE 6
Type Compatibility • Two types are said to be compatible (really just a form of equivalence) if they can both be used in a given context. • Type t 1 is said to be assignment compatible to type t 2 if a value of type t 1 can appear in an assignment statement with a left hand side argument of type t 2. • The left hand side argument is treated as an lvalue, or location of an element of type t 2, while the right hand side expression is an r-value that is directly of type t 1. Lecture #21 PLP Spring 2004, UF CISE 7
Type Conversion • Type conversions may be implicit or explicit. • Consider the following C code: int x = 3; x = 2. 3 + x/2; What implicit type conversions occur? • Consider this code: x = (int)(2. 3 + double(x/2)); • Java provides implicit widening conversions, but no narrowing conversions. • C provides the generic void * pointer type that may contain and be converted to a pointer of any type. • I’ll talk about static and dynamic casts in C++ in a future lecture. Lecture #21 PLP Spring 2004, UF CISE 8