Compiler Design - CSE 504: Type Checking
Compiler Design - CSE 504: Type Checking
Type Checking
Static Checking
Token Stream
Parser
Static Checker
Intermediate Code
Type checks: operator applied to incompatible operands? Flow of control checks: break (outside while?) Uniqueness checks: labels in case statements Name related checks: same name?
Type Checking
Problem: Verify that a type of a construct matches that expected by its context. Examples: mod requires integer operands (PASCAL) * (dereferencing) applied to a pointer a[i] indexing applied to an array f(a1, a2, , an) function applied to correct arguments.
Type Systems
A collection of rules for assigning type expressions to the various parts of a program. Based on: Syntactic constructs, notion of a type. Example: If both operators of +, -, * are of type integer then so is the result. Type Checker: An implementation of a type system.
Syntax Directed.
Sound Type System: eliminates the need for checking type errors during run time.
Type Expressions
Implicit Assumptions:
Expressions Statements
Type Constructors
Arrays Records Sets Pointers Functions
Boolean
Real Enumerations Void Variables
Character
Integer Sub-ranges Error Names
cell = record
x
x char char
pointer integer
x char
pointer integer
x ptr
Tree
DAG
Structured Types
{E.type = pointer(E1.tye)}
{E.type = if (E1.type = arrow(S, T) & E2.type = S, then T else err}
S -> while E do S1
S -> S1; S2
We need a precise definition for type equivalence Interaction between type equivalence and type representation
type vector = array [1..10] of real type weight = array [1..10] of real var x, y: vector; z: weight
Example:
12
Structural Equivalence
Definition: by Induction
Same basic type Same constructor applied to SE Type Same DAG Representation
Do not include array bounds when they are passed as parameters Other applied representations (More compact) Does not check for cycles Later improve it.
13
Recursive Types
Where: Linked Lists, Trees, etc. How: records containing pointers to similar records Example: type link = cell; cell = record info: int; next = link end Representation: cell = record cell = record x x x ptr x
x
x ptr
cell
Recursive Types in C
Using structural equivalence for all types Except for records -> name equivalence
Example:
struct cell {int info; struct cell * next;} Use the acyclic representation Names declared before use except for pointers to records. Cycles potential due to pointers in records Testing for structural equivalence stops when a record constructor is reached ~ same named record type?
Name use: name cell becomes part of the type of the record.
16
Overloaded Symbol: one that has different meanings depending on its context Example: Addition operator + Resolving (operator identification): overloading is resolved when a unique meaning is determined. Context: it is not always possible to resolve overloading by looking only the arguments of a function
17
Overloading Example
function * (i, j: integer) return complex; function * (x, y: complex) return complex; * Has the following types: arrow(tuple(integer, integer), integer) arrow(tuple(integer, integer), complex) arrow(tuple(complex, complex), complex) int i, j; k = i * j;
Department of Computer Science, Stony Brook University
18
Polymorphic Functions
Defn: a piece of code (functions, operators) that can be executed with arguments of different types. Examples: Built in Operator indexing arrays, pointer manipulation
20
21
Type Variables
Why: variables representing type expressions allow us to talk about unknown types.
Application: check consistent usage of identifiers in a language that does not require identifiers to be declared before usage.
Type Inference Problem: Determine the type of a language constant from the way it is used.
22
23
Subsripts i and o distinguish between the inner and outer occurrences of deref, respectively.
Department of Computer Science, Stony Brook University
24
Distinct occurrences of a p.f. in the same expression need not have arguments of the same type.
deref ( deref (q)) Replace with fresh variable and remove (i, o)
Use unification: check if s and t can be made structurally equivalent by replacing type vars by the type expression.
25
26
fresh (t): replaces bound vars in t by fresh vars. Returns pointer to a node representing result.type. fresh( .pointer() -> ) = pointer(1) -> 1.
unify (m, n): unifies expressions represented by m and n.
27
: 1
o : 1
-> : 3 pointer : 2
i : 4
m-> : 6 pointer : 5
n-> : 6
pointer : 5 pointer : 8 integer : 7
28
: 8
o : 1
i : 4