Lecture Outline. Type systems and their expressiveness. Type Checking in COOL (II) Type checking with SELF_TYPE in COOL

Similar documents
Lecture Outline. Type systems and their expressiveness. Type Checking in COOL (II) Type checking with SELF_TYPE in COOL

Type Checking in COOL (II) Lecture 10

More Static Semantics. Static. One-Slide Summary. Lecture Outline. Typing Rules. Dispatch Rules SELF_TYPE

More Static Semantics

More Static Semantics

Lecture Outline. COOL operational semantics. Operational Semantics of Cool. Motivation. Notation. The rules. Evaluation Rules So Far.

Scoping rules match identifier uses with identifier definitions. A type is a set of values coupled with a set of operations on those values.

Passing Out Review Forms

Lecture Outline. COOL operational semantics. Operational Semantics of Cool. Motivation. Lecture 13. Notation. The rules. Evaluation Rules So Far

Types. Type checking. Why Do We Need Type Systems? Types and Operations. What is a type? Consensus

type environment updated subtype sound

Operational Semantics. One-Slide Summary. Lecture Outline

Operational Semantics of Cool

The Compiler So Far. Lexical analysis Detects inputs with illegal tokens. Overview of Semantic Analysis

Anatomy of a Compiler. Overview of Semantic Analysis. The Compiler So Far. Why a Separate Semantic Analysis?

type environment updated subtype sound

Overview of Semantic Analysis. Lecture 9

Grade Weights. Language Design and Overview of COOL. CS143 Lecture 2. Programming Language Economics 101. Lecture Outline

Announcements. Written Assignment 2 Due Monday at 5:00PM. Midterm next Wednesday in class, 11:00 1:00. Midterm review session next Monday in class.

Project 6 Due 11:59:59pm Thu, Dec 10, 2015

Semantic Analysis. Lecture 9. February 7, 2018

Operational Semantics of Cool

Compilers. Cool Semantics II. Alex Aiken

Outline. Java Models for variables Types and type checking, type safety Interpretation vs. compilation. Reasoning about code. CSCI 2600 Spring

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

Static Semantics. Lecture 15. (Notes by P. N. Hilfinger and R. Bodik) 2/29/08 Prof. Hilfinger, CS164 Lecture 15 1

1 Lexical Considerations

Lexical Considerations

Announcements. Written Assignment 2 due today at 5:00PM. Programming Project 2 due Friday at 11:59PM. Please contact us with questions!

CS412/CS413. Introduction to Compilers Tim Teitelbaum. Lecture 17: Types and Type-Checking 25 Feb 08

Operational Semantics

Programming Assignment IV

The code generator must statically assign a location in the AR for each temporary add $a0 $t1 $a0 ; $a0 = e 1 + e 2 addiu $sp $sp 4 ; adjust $sp (!

Lexical Considerations

Lecture 16: Static Semantics Overview 1

Lecture 7: Type Systems and Symbol Tables. CS 540 George Mason University

CS152: Programming Languages. Lecture 23 Advanced Concepts in Object-Oriented Programming. Dan Grossman Spring 2011

Object-Oriented Concepts

Programming Assignment IV Due Monday, November 8 (with an automatic extension until Friday, November 12, noon)

Syntax Errors; Static Semantics

Outline. General properties of type systems. Types in programming languages. Notation for type rules. Common type rules. Logical rules of inference

HAS-A Relationship. If A uses B, then it is an aggregation, stating that B exists independently from A.

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler Front-End

The role of semantic analysis in a compiler

Inheritance. Inheritance Reserved word protected Reserved word super Overriding methods Class Hierarchies Reading for this lecture: L&L

Semantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler so far

CMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics

Written Assignment 5 Due??

Design Patterns: State, Bridge, Visitor

Polymorphism. CMSC 330: Organization of Programming Languages. Two Kinds of Polymorphism. Polymorphism Overview. Polymorphism

Operational Semantics of Cool

IC Language Specification

CSCE 314 Programming Languages. Type System

Run-Time Organization

Project 2 Due 11:59:59pm Wed, Mar 7, 2012

Type Checking. Outline. General properties of type systems. Types in programming languages. Notation for type rules.

Scoping and Type Checking

Reference Grammar Meta-notation: hfooi means foo is a nonterminal. foo (in bold font) means that foo is a terminal i.e., a token or a part of a token.

Cunning Plan. One-Slide Summary. Functional Programming. Functional Programming. Introduction to COOL #1. Classroom Object-Oriented Language

Object-Oriented Concepts and Design Principles

Rules and syntax for inheritance. The boring stuff

Lecture Topics. Administrivia

CS107 Handout 37 Spring 2007 May 25, 2007 Introduction to Inheritance

Chapter 4 Defining Classes I

Topics Covered Thus Far. CMSC 330: Organization of Programming Languages. Language Features Covered Thus Far. Programming Languages Revisited

(Not Quite) Minijava

The Compiler So Far. CSC 4181 Compiler Construction. Semantic Analysis. Beyond Syntax. Goals of a Semantic Analyzer.

Global Optimization. Lecture Outline. Global flow analysis. Global constant propagation. Liveness analysis. Local Optimization. Global Optimization

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

First IS-A Relationship: Inheritance

Tail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)

CMSC 330: Organization of Programming Languages

Example: Count of Points

Announcements. Working on requirements this week Work on design, implementation. Types. Lecture 17 CS 169. Outline. Java Types

301AA - Advanced Programming [AP-2017]

VIRTUAL FUNCTIONS Chapter 10

CS152: Programming Languages. Lecture 24 Bounded Polymorphism; Classless OOP. Dan Grossman Spring 2011

Lecture 5: Methods CS2301

CSE P 501 Exam 8/5/04

Compiler construction 2009

Compilers and computer architecture: Semantic analysis

Java: introduction to object-oriented features

CSE 331 Software Design and Implementation. Lecture 14 Generics 2

Overriding המחלקה למדעי המחשב עזאם מרעי אוניברסיטת בן-גוריון

Advanced Programming - JAVA Lecture 4 OOP Concepts in JAVA PART II

CSE 331 Software Design and Implementation. Lecture 14 Generics 2

Type checking. Jianguo Lu. November 27, slides adapted from Sean Treichler and Alex Aiken s. Jianguo Lu November 27, / 39

OBJECT ORIENTED PROGRAMMING USING C++

The Decaf Language. 1 Lexical considerations

Winter Compiler Construction Who. Mailing list and forum

More Relationships Between Classes

PROGRAMMING LANGUAGE 2

M301: Software Systems & their Development. Unit 4: Inheritance, Composition and Polymorphism

Object-oriented programming. and data-structures CS/ENGRD 2110 SUMMER 2018

Name Return type Argument list. Then the new method is said to override the old one. So, what is the objective of subclass?

Project 5 Due 11:59:59pm Wed, Nov 25, 2015 (no late submissions)

COL728 Minor2 Exam Compiler Design Sem II, Answer all 5 questions Max. Marks: 20

A Short Summary of Javali

Lectures 20, 21: Axiomatic Semantics

Graphical Interface and Application (I3305) Semester: 1 Academic Year: 2017/2018 Dr Antoun Yaacoub

Transcription:

Lecture Outline Type systems and their expressiveness Type Checking in COOL (II) Type checking with SELF_TYPE in COOL Error recovery in semantic analysis Adapted from Lectures by Profs. Alex Aiken and George Necula (UCB) CS781(Prasad) L21TC 1 CS781(Prasad) L21TC 2 Expressiveness of Static Type Systems A static type system enables a compiler to detect many common programming errors The cost is that some correct programs are disallowed Some argue for dynamic type checking instead Others argue for more expressive static type checking But more expressive type systems are also more complex CS781(Prasad) L21TC 3 Dynamic And Static Types The dynamic type of an object is the class C that is used in the new C expression that created it A run-time notion Even languages that are not statically typed have the notion of dynamic type The static type of an expression is a notation that captures all possible dynamic types the expression could take A compile-time notion CS781(Prasad) L21TC 4 Dynamic and Static Types. (Cont.) In early type systems, the set of static types corresponded directly with the dynamic types Soundness theorem: for all expressions E dynamic_type(e) = static_type(e) (in all executions, E evaluates to values of the type inferred by the compiler) This gets more complicated in advanced type systems CS781(Prasad) L21TC 5 Dynamic and Static Types in COOL x has static type A class A { class B inherits A { A x new A; x new B; Here, x s value has dynamic type A Here, x s value has dynamic type B A variable of static type A can hold values of static type B, if B A CS781(Prasad) L21TC 6

Dynamic and Static Types Soundness theorem for the Cool type system: E. dynamic_type(e) static_type(e) Why is this Ok? All operations that can be used on an object of type C can also be used on an object of type D C Such as fetching the value of an attribute Or invoking a method on the object Subclasses can only add attributes or methods Methods can be redefined but with same type! An Example class Count { i : int 0; inc () : Count { { i i + 1; self; Class Count incorporates a counter i The inc method works for any subclass What is the type of inc? But there is disaster lurking in the type system CS781(Prasad) L21TC 7 CS781(Prasad) L21TC 8 An Example (Cont.) Consider a subclass Stock of Count class Stock inherits Count { name : String; -- name of item And the following use of Stock: Stock a (new Stock).inc (); a.name Type checker error! CS781(Prasad) L21TC 9 What went wrong? (new Stock).inc() has dynamic type Stock So it is legitimate to write Stock a (new Stock).inc () But this is not well-typed (new Stock).inc() has static type Count The type checker loses type information This makes inheriting inc useless So, we must redefine inc for each of the subclasses, with a specialized return type CS781(Prasad) L21TC 10 SELF_TYPE to the Rescue We will extend the type system Insight: inc returns self Therefore the return value has same type as self Which could be Count or any subtype of Count! Recall that method is type checked once, and is required to guarantee type correctness of all possible/potential invocations. Introduce the keyword SELF_TYPE to use for the return value of such functions, and modify typing rules to handle SELF_TYPE CS781(Prasad) L21TC 11 SELF_TYPE to the Rescue (Cont.) SELF_TYPE allows the return type of inc to change when inc is inherited Modify the declaration of inc to read inc() : SELF_TYPE { The type checker can now prove: C,M (new Count).inc() : Count C,M (new Stock).inc() : Stock The program from before is now well typed CS781(Prasad) L21TC 12

Self Motivating Examples and Issues CS781(Prasad) L21TC 13 self names the receiver object inside a method body. In expression languages such as Cool, self can be the return expression to conveniently compose a number of side-effect causing operations. Cf. signatures of << and >> in C++ f() : C { { ; self; g() : C { { ; self; h() : C { { ; self; (new C). f(). g(). h() ; CS781(Prasad) L21TC 14 Method inheritance id() : C { self class D inherits C { D d <- (new D). id(); The type of the returned result of id() is C. This is too conservative the static type checker bans this reasonable invocation of id() on a D-object. In a dynamically typed language, the type checking is done in the context of a specific use. In a statically typed language, the type checking is done just once for all potential uses. SELF_TYPE id() : SELF_TYPE { self class D inherits C { D d <- (new D). id(); An enhancement to the type language allows natural code reuse in a statically typed language. The semantics of SELF_TYPE depends on the class in which the method is inherited (actually, it stands for the type of the receiver object). CS781(Prasad) L21TC 15 CS781(Prasad) L21TC 16 Unsound Typing Legal uses of SELF_TYPE in Cool id() : SELF_TYPE { new C class D inherits C { D d <- (new D). id(); Allowing this program causes a type error at run-time. An instance of super-class C is assigned to a variable of sub-type D. Cf. id() : C { self CS781(Prasad) L21TC 17 s : SELF_TYPE <- new SELF_TYPE; id() : SELF_TYPE { let x: SELF_TYPE <- self, in x Instead of freezing the type, the use of SELF_TYPE permits carrying around a type equality constraint. CS781(Prasad) L21TC 18

Expressions with type SELF_TYPE f() : SELF_TYPE { self g(c c1, C c2) : SELF_TYPE { self h() : SELF_TYPE { g(new C, self) class D inherits C { i() : SELF_TYPE { g(new D, new D) CS781(Prasad) L21TC 19 Expressions in Java C f() { return this; C g(c c1, C c2) { return this; C h() { return g(new C(), this); class D extends C { C g(d d1, D d2) { return h(); C i() { return g(new D(), new D()) CS781(Prasad) L21TC 20 Java specifics String g(c c1, C c2) { return "\t ---> g(c,c) run\n"; class D extends C { String g(d d1, D d2) { return "\t ---> g(d,d) run\n"; class ThatOverload { public static void main(string[] args) { C c = new C(); D d = new D(); System.out.print("\t g(c,c) called" + d.g(c,c)); System.out.print("\t g(d,c) called" + d.g(d,c)); System.out.print("\t g(c,d) called" + d.g(c,d)); System.out.print("\t g(d,d) called" + d.g(d,d)); int e(d d) { return 0; C j() { return new C(); class D extends C { int k() {return this.e(new D()); // return e(new D()); // ambiguous in Java to coerce or to inherit // return super.e(new D()); // inherited // no obvious way to invoke local e int e(c c) { return 1 + super.e(this) ; CS781(Prasad) L21TC 21 CS781(Prasad) L21TC 22 Without SELF_TYPE id(s : C) : C { C x <- s class D inherits C { C c <- (new C). id(new D); D d <- (new D). id(new C); A subclass instance can be coerced to a class instance. CS781(Prasad) L21TC 23 Illegal Use of SELF_TYPE id(s : SELF_TYPE) : SELF_TYPE { SELF_TYPE x <- s class D inherits C { C c <- (new D); c. id(new C); If permitted, causes type violations at run-time as follows: D s <- new C; ; D x <- s; CS781(Prasad) L21TC 24

Coercion and SELF_TYPE: Illegal Cool id(s, t : SELF_TYPE) : bool { s == t Open-ended issues class D inherits C { C c <- (new C); D d <- (new D); c. id(c, d); If formals can have SELF_TYPE, should this type check? CS781(Prasad) L21TC 25 CS781(Prasad) L21TC 26 Notes on extensions The use of SELF_TYPE can be extended (such as for a formal) in a strongly typed language by performing run-time type checks and throwing exceptions to signal errors. Check that the run-time type of the actual argument is compatible with that of the receiver. Cf. Java s approach to strong typing Why is SELF_TYPE not permitted in a case construct in Cool? CS781(Prasad) L21TC 27 Require that the actual arguments corresponding to the formal parameters of a method with type SELF_TYPE be of type SELF_TYPE. Is this typing rule sound? Is this extension natural and worthwhile? If the functions can return l-values, is the type system sound? Check assignments CS781(Prasad) L21TC 28 Interaction between Overloading and Overriding To match the message with a method, C++ searches the ancestor classes of an object. The class that defines the message name is further searched to match the entire signature. Even if a better match is inheritable, it will not be considered. Thus C++ differs from Java. class A { public: void test(double d){ class B : public A { public: void test(int i) { Error: B b; b.test(2.5); Corrected: void B::test(double d) { A::test(d); Back to Type system with SELF_TYPE CS781(Prasad) L21TC 29 CS781(Prasad) L21TC 30

Notes About SELF_TYPE SELF_TYPE is a static type, not dynamic type Cf. Eiffel s approach It helps the type checker to keep better track of types It enables the type checker to accept more correct programs In short, having SELF_TYPE increases the expressive power of the type system CS781(Prasad) L21TC 31 SELF_TYPE and Dynamic Types (Example) What can be the dynamic type of the object returned by inc? Answer: whatever could be the type of self class A inherits Count { ; class B inherits Count { ; class C inherits Count { ; (inc could be invoked through any of these classes) Answer: Count or any subtype of Count CS781(Prasad) L21TC 32 SELF_TYPE and Dynamic Types (Example) In general, if SELF_TYPE appears textually in the class C as the declared type of E then dynamic_type(e) C Note: The meaning of SELF_TYPE depends on where it appears We write SELF_TYPE C to refer to an occurrence of SELF_TYPE in the body of C This suggests a typing rule: SELF_TYPE C C (*) Type Checking Rule (*) has an important consequence: In type checking, it is always safe to replace SELF_TYPE C by C This suggests one way to handle SELF_TYPE : Replace all occurrences of SELF_TYPE C by C This would be correct but it is like not having SELF_TYPE at all! CS781(Prasad) L21TC 33 CS781(Prasad) L21TC 34 Operations on SELF_TYPE Recall the operations on types T 1 T 2 T 1 is a subtype of T 2 lub(t 1,T 2 ) the least-upper bound of T 1 and T 2 We must extend these operations to handle SELF_TYPE Typically, type restrictions are motivated by assignment-like operations in the context of a class hierarchy. Extending Let T and T be any types but SELF_TYPE. There are four cases in the definition of 1. SELF_TYPE C SELF_TYPE C In Cool, we never need to compare SELF_TYPEs coming from different classes 2. SELF_TYPE C T if C T SELF_TYPE C can be any subtype of C, including C Thus this is the most flexible rule we can allow CS781(Prasad) L21TC 35 CS781(Prasad) L21TC 36

Extending (Cont.) Extending lub(t,t ) 3. T SELF_TYPE C is always false Note: SELF_TYPE C can denote any subtype of C. 4. T T (according to the rules from before) Based on these rules we can extend lub Let T and T be any types but SELF_TYPE. Again there are four cases: 1. lub(self_type C, SELF_TYPE C ) = SELF_TYPE C 2. lub(self_type C, T) = lub(c, T) This is the best we can do because SELF_TYPE C C 3. lub(t, SELF_TYPE C ) = lub(c, T) 4. lub(t, T ) defined as before CS781(Prasad) L21TC 37 CS781(Prasad) L21TC 38 Where can SELF_TYPE appear in COOL? The parser checks that SELF_TYPE appears only where a type is expected But SELF_TYPE is not allowed everywhere a type can appear: 1. class T inherits T { T, T cannot be SELF_TYPE Because SELF_TYPE is never a dynamic type 2. x : T T can be SELF_TYPE An attribute whose type is SELF_TYPE C Where can SELF_TYPE appear in COOL? 3. let x : T in E T can be SELF_TYPE x has a type SELF_TYPE C 4. new T T can be SELF_TYPE Creates an object of the same type as self 5. m@t(e 1,,E n ) T cannot be SELF_TYPE CS781(Prasad) L21TC 39 CS781(Prasad) L21TC 40 Where SELF_TYPE cannot appear in COOL? Typing Rules for SELF_TYPE 6. m(x : T) : T { Only T can be SELF_TYPE! What could go wrong if T were SELF_TYPE? class A { comp(x : SELF_TYPE) : Bool { class B inherits A { b : int; comp(x : SELF_TYPE) : Bool { x.b let x : A new B in x.comp(new A); CS781(Prasad) L21TC 41 Since occurrences of SELF_TYPE depend on the enclosing class we need to carry more context during type checking New form of the typing judgment: O,M,C e : T (An expression e occurring in the body of C has static type T given a variable type environment O and method signatures M) CS781(Prasad) L21TC 42

Type Checking Rules The next step is to design type rules using SELF_TYPE for each language construct Most of the rules remain the same except that and lub are the new ones Example: O(Id) = T 0 O,M,C e 1 : T 1 T 1 T 0 What s Different? Recall the old rule for dispatch O,M,C e 0 : T 0 M O,M,C e n : T n M(T 0, f) = (T 1,,T n,t n+1 ) T n+1 SELF_TYPE T i T i 1 i n O,M,C e 0.f(e 1,,e n ) : T n+1 O,M,C Id e 1 : T 1 CS781(Prasad) L21TC 44 CS781(Prasad) L21TC 43 What s Different? If the return type of the method is SELF_TYPE then the type of the dispatch is the type of the dispatch expression: O,M,C e 0 : T 0 M O,M,C e n : T n M(T 0, f) = (T 1,,T n, SELF_TYPE) T i T i 1 i n O,M,C e 0.f(e 1,,e n ) : T 0 CS781(Prasad) L21TC 45 What s Different? Note that this rule handles the Stock example Formal parameters cannot be SELF_TYPE Actual arguments can be SELF_TYPE The extended relation handles this case The type T 0 of the dispatch expression could be SELF_TYPE Which class is used to find the declaration of f? Answer: it is safe to use the class where the dispatch appears CS781(Prasad) L21TC 46 Static Dispatch Recall the original rule for static dispatch O,M,C e 0 : T 0 M O,M,C e n : T n T 0 T M(T, f) = (T 1,,T n,t n+1 ) T n+1 SELF_TYPE T i T i 1 i n O,M,C e 0 @T.f(e 1,,e n ) : T n+1 CS781(Prasad) L21TC 47 Static Dispatch If the return type of the method is SELF_TYPE we have: O,M,C e 0 : T 0 M O,M,C e n : T n T 0 T M(T, f) = (T 1,,T n,self_type) T i T i 1 i n O,M,C e 0 @T.f(e 1,,e n ) : T 0 CS781(Prasad) L21TC 48

Static Dispatch Why is this rule correct? If we dispatch a method returning SELF_TYPE in class T, don t we get back a T? No. SELF_TYPE is the type of the self parameter, which may be a subtype of the class in which the method appears The static dispatch class cannot be SELF_TYPE That s dynamic dispatch! New Rules There are two new rules using SELF_TYPE O,M,C O,M,C self : SELF_TYPE C new SELF_TYPE : SELF_TYPE C There are a number of other places where SELF_TYPE is used CS781(Prasad) L21TC 49 CS781(Prasad) L21TC 50 Summary of SELF_TYPE The extended and lub operations can do a lot of the work. Implement them to handle SELF_TYPE SELF_TYPE can be used only in a few places. Be sure it isn t used anywhere else. A use of SELF_TYPE always refers to any subtype in the current class The exception is the type checking of dispatch. The method return type of SELF_TYPE might have nothing to do with the current class Why cover SELF_TYPE? SELF_TYPE is a research idea It adds more expressiveness to the type system SELF_TYPE is itself not so important Rather, SELF_TYPE is meant to illustrate that type checking can be quite subtle In practice, there should be a balance between the complexity of the type system and its expressiveness CS781(Prasad) L21TC 51 CS781(Prasad) L21TC 52 Error Recovery As with parsing, it is important to recover from type errors Detecting where errors occur is easier than in parsing There is no reason to skip over portions of code The Problem: What type is assigned to an expression with no legitimate type? This type will influence the typing of the enclosing expression CS781(Prasad) L21TC 53 Error Recovery Attempt Assign type Object to ill-typed expressions let y : Int x + 2 in y + 3 Since x is undeclared its type is Object But now we have Object + Int This will generate another typing error We then say that that Object + Int = Object Then the initializer s type will not be Int a workable solution but with cascading errors CS781(Prasad) L21TC 54

Better Error Recovery We can introduce a new type called No_type for use with ill-typed expressions Define No_type C for all types C Every operation is defined for No_type With a No_type result Only one typing error for: let y : Int x + 2 in y + 3 Notes A real compiler would use something like No_type Cf. in Denotational Semantics However, there are some implementation issues The class hierarchy is not a tree anymore The Object solution is adequate for the project CS781(Prasad) L21TC 55 CS781(Prasad) L21TC 56