Download presentation
Presentation is loading. Please wait.
1
Semantic Analysis Type Checking
2
Type Checking Type checking Example typing rules
Check type safety against typing rules During the semantic analysis phase Example typing rules Type rule for built in arithmetic operators E.g., operands of % should be integer E.g., operands of + have to be consistent (all integers or all floats) A function has the same number of formal and actual parameters The types of the formal and actual parameters of a function have to match The array range is not violated
3
Type Checking -- Attribute Grammar
First handle type definitions Statement for basic type definitions (discussed earlier) D id L addtype (id.entry, L.type) L , id L1 L.type := L1.type; addtype (id.entry, L1.type) L : T L.type := T.type T int T.type := integer T real T.type := real … Then perform type checking within statements
4
Type Checking -- Attribute Grammar
Type checking for the statements from bottom up L S; L1 L.type if (S.type = void and L1.type = void) then void else type error S id := E S.type := if (id.type = E.type) then void else type error E E1 + T if (E1.type = T.type) then E.type = E1.type else type error S while C do S1 S.type := if C.type = Boolean then S1.type else type error S if C then S1 else S2 S.type := if C.type = Boolean then ? else type error if (S1.Type = void and S2.Type = void) then return void
5
Type Definitions Basic Types Compound types
Integer, real, Boolean, char, etc. Compound types Pointers Type = pointer (basic-type) Array Type = array (dimension) Structure Type = structure with the types of all fields Function Type = function with the types of all parameters
6
Type Definitions Type equivalence Subtypes array(a,b) array(c,d)
In some situations, like parameter passing, they are structurally equivalent, or they have a common super type of 2D array struct A { int ai; char ac; } struct B { int bi; char bc; } A and B are structurally equivalent Subtypes Define subtype relation e.g., A B: A is a subtype of B A may be accepted anywhere B is expected
7
Static and Dynamic Type Checking
Static typing Types can be determined and checked at compilation time A variable has a single type throughout its lifetime More conservative, correct program may be rejected Dynamic typing Types are defined and checked at execution time Type may change during execution Degrading performance for type checking at run time Combined Some type checking may not be done fully statically Do all possible checking statically, and leave the uncertain type checking till run time
8
Static and Dynamic Type Checking
Example: static type checking is conservative Class A { cat: Category; a(): …; } Class B inherits A { cat = B; b(): …; } Class C inherits A { cat = C; c(): …; } B A, C A F (obj: A) { switch obj.cat: B: obj.a(); obj.b(); C: obj.a(); obj.c(); default: … endcase; } The program would be correct with dynamic type checking But will fail on static type checking No function b() in class A
9
Static and Dynamic Type Checking
Example: static type checking is conservative function f(x) { return x < 10 ? y : z(); } if (…) then f(5); else f(15); The program would be correct with dynamic type checking Because only one branch is executed and type checked But will fail on static type checking Inconsistent function type Assume that y and z() are of different types
10
Static and Dynamic Type Checking
Static type checking -- example rules Type matching for functions and expressions Type matching (Boolean) for conditional statements Java also checks Illegitimate type casting (only allowed between sub-super types) Accesses to private fields Dynamic type checking -- example rules Divide by 0, array bound OCaml combines static and dynamic type checking E.g., check array bound errors during dynamic type checking Script languages such as Python, Ruby only perform dynamic type checking: Use general static typing rules
11
Static Type Checking -- Correctness
Soundness Given type rule X, a static checker is supposed to assure X A static checker is sound if it never accepts a program that may violate X during execution (given any input) No false negatives, never have: “a faulty behavior is not caught” Completeness A static checker is complete if it never rejects a program P if P will never violate X during its execution with any input No false positives In general, static checker is designed to be sound, but not complete
12
Static Type Checking -- Type Inference
Language without type definitions Still can perform static type checking Need to perform type inference to assign types to variables First proposed and applied to -calculus, then ML, then Haskell Type inference method Build parse tree (or AST) Assign type variables to identifiers Generate constraints based on (1) Constants (2) Built-in operators +. *, %, etc., (3) Typed functions (e.g. in ML, first, tail) All the steps above can be done during parsing (attribute grammar) Solve constraints Undetermined type variables Has polymorphic type Use the closest super type for the variable Haskell uses bottom up type inference on parse tree Possible because it has very strict typing rules - Overloaded operators should be type consistent e.g., int = int + int, real = real + real - IO has strict type assignments
13
Static Type Checking -- Type Inference
You can build a graph (matrix or list) to show the relations of variables. If a type variable has relation to another, mark the matrix. During inference, whenever one type variable changes value, check all those that has relations to it and propagate the check. Or, you can maintain another list to record the type variables that have changed in a round, and propagate the check round by round. Static Type Checking -- Type Inference Example Example type rules Operands of arithmetic operators have to be one of the number types (int, float, double) (sub-super type is fine), and the result should be a super type of the operands Operands and the result of % have to be integer Array index has to be natural numbers (integer) Example program Input (a, s, t, n); x := a + 2.5; y := s % t; L = (“this”, “is”, “a”, “list”); elem = L[n]; m := y / n; v = m * a; If / is overloaded for int and float/double, then “y / n” should be integer division Type error: y := s % x float x.type double a.type double y.type = s.type = t.type = int L.type = array of strings elem.type = string n.type = int m.type = int v.type double
14
Strong Typing and Weak Typing
A language is strongly typed Type errors are always detected, statically or dynamically There is strict enforcement of type rules with no exceptions The line between strong/week typing does not have consensus Ada, Java, and Haskell are strongly typed C is almost strongly typed, but union is the loophole Cannot assure type consistency with union
15
Strong Typing and Weak Typing
Coercion and polymorphism blurs the line on strong or weak typing Coercion: such as type casting in C Especially dangerous for pointer type casting Coercion example x = 1; y = “2”; z = x + y JavaScript: z = 12 Visual Basic: z = 3 Polymorphism Earlier example of inconsistent return type Make type checking difficult Python is strongly or weakly typed Still being debated, mostly consider it as strongly typed But how it handles polymorphism makes this debatable
16
Type Checking -- Summary
Read Chapter 6 Sections 6.3, 6.5
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.