140 likes | 299 Views
Type Checking. Aggelos Kiayias Computer Science & Engineering Department The University of Connecticut 371 Fairfield Road, Unit 1155 Storrs, CT 06269-1155. aggelos@cse.uconn.edu http://www.cse.uconn.edu/~akiayias. Static Checking.
E N D
Type Checking Aggelos Kiayias Computer Science & Engineering Department The University of Connecticut 371 Fairfield Road, Unit 1155 Storrs, CT 06269-1155 aggelos@cse.uconn.edu http://www.cse.uconn.edu/~akiayias
Static Checking • Some syntactic/semantic properties of the source language are not appropriate for incorporation into the grammar of the language. • They will be checked separately. • Static Checking/ Dynamic Checking. • Static checking examples: • Type checks. • Flow-of-control checks. • Uniqueness checks. • Name-related checks.
Type Expressions • The type of a language construct will be denoted by a “type- expression.” • Type-expressions are either basic types or they are constructed from basic types using type constructors. • Basic types: boolean, char, integer, real, type_error, void • array(I,T)where T is a type-expression and I is an integer-range. E.g. int A[10]has the type expression array({0,..,9},integer) • We can take “cartesian products” of type-expressions. E.g. struct entry {char letter; int value; };is of type (letter xchar) x (value xinteger)
Type Expressions,II • Pointers.int* aaaa is of type pointer(integer). • Functions: int divide(int i, int j)is of type integer x integer integer Representing type expressions as trees e.g. char x char pointer(integer) x pointer char integer char
Type Systems • A Type-system: collection of rules for assigning type-expressions to the variable parts of a program. • A type-checker implements a type-system. • It is most convenient to implement a type-checker within the semantic rules of a syntax-directed definition (and thus it will be implemented during translation). • Many checks can be done statically (at compilation). • Not all checks can be done statically. E.g. int A[10]; int i; … … ; printf(“%d”,A[i]); • Recent security concerns about type-checking (the buffer overflow vulnerability).
A simple type-checker. • Use a synthesized attribute called type to carry the type expression of the corresponding language construct. • We will use the grammar: PRODUCTION P D ; E D D ; D | id : T T char | integer | array [ num ] of T| ^T E literal | num | id |E mod E |E [E] |E^ Examples CODESome TypesExpressions key:integer; array[256] of char table[i] key mod 1999 ^integer ppt^
A simple type-checker, II Dealing with declarations (no type-checking yet) Necessary bookkeeping for symbol-table construction + type checking PRODUCTION Semantic Rule P D ; E { } D D ; D { } D id : T { addtype(id.entry, T.type) } T char {T.type = char } T integer {T.type = integer } T array [ num ] of T {T.type=array(1..num.val,T.type)} T ^T {T.type = pointer(T.type) }
A simple type-checker, III continuation… PRODUCTION Semantic Rule E literal {E.type = char } E num {E.type = integer } E id {E.type = lookup(id.entry)} E E1mod E2 {E.type = if (E1.type == integer) and (E2.type == integer) then integer else type_error } E E1[E2] {E.type = if (E2.type == integer) and (E1.type == array(s,t)) then t else type_error } E E1^ {E.type = if (E1.type == pointer(t)) then t else type_error } In a similar fashion we can add boolean types.
Extension to Type-Checking of Statements PRODUCTION Semantic Rule S id := E{S.type = if (lookup(id.entry)==E.type) then void else type_error } S if E then S1 {S.type = if (E.type == boolean) then S1.type else type_error } S while E do S1 {S.type = if (E.type == boolean) then S1.type else type_error } S S1; S2 {S.type = if (S1.type == void) and (S2.type == void) then void else type_error } Tough!
Structural Equivalence of Types Recursive procedure: function sequiv(s,t):boolean; begin if s and t are the same basic type then return true else if s=array(s1,s2) and t=array(t1,t2) then return sequiv(s1,t1) and sequiv(s2,t2) else if s=s1 x s2 and t=t1 x t2 then return sequiv(s1,t1) and sequiv(s2,t2) else if s=pointer(s1) and t=pointer(t1) return sequiv(s1,t1) else if s=s1 s2 and t=t1 t2 then return sequiv(s1,t1) and sequiv(s2,t2) else return false end
Type Checking of Functions Additional type production: T T1T2{T.type = T1.typeT2.type } E E1(E2) {E.type = if (E2.type==s) and (E1.type==st) then t else type_error }
Type Coercions • Tolerate type mismatch in expressions if no information gets lost. PRODUCTION Semantic Rule E num {E.type = integer } E num.num {E.type = real } E id {E.type = lookup(id.entry)} E E1op E2 {E.type = if (E1.type == integer) and (E2.type == integer) then integer else if (E1.type == integer) and (E2.type == real) then real else if (E1.type == real) and (E2.type == integer) then real else if (E1.type == real) and (E2.type == real) then real else type_error }
Overloading • Expressions might have a multitude of types. • Example with functions: E id {E.types = lookup(id.entry)} E E1(E2) {E.types = { t | there exists a s in E2.types such that st belongs to E1.types } Type error will occur when E.types becomes empty for some expression.