type-checking - stanford university...static type checking in decaf consists of two separate...

142
Type-Checking

Upload: others

Post on 23-May-2020

7 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Type-Checking

Page 2: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Announcements

● Written Assignment 2 due today at 5:00PM.

● Programming Project 2 due Friday at 11:59PM.

● Please contact us with questions!● Stop by office hours!● Email the staff list!● Ask on Piazza!

Page 3: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming
Page 4: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Announcements

● Midterm exam one week from today, July 25th from 11:00AM – 1:00PM here in Thornton 102.

● Covers material up to and including Earley parsing.

● Review session in class next Monday.● Practice exam released; solutions will be

distributed on Monday.● SCPD Students: Exam will be emailed out on

July 25th at 11:00AM. You can start the exam any time between 11:00AM on July 25th and 11:00AM on July 26th.

Page 5: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Where We Are

Lexical Analysis

Semantic Analysis

Syntax Analysis

IR Generation

IR Optimization

Code Generation

Optimization

SourceCode

MachineCode

Page 6: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Page 7: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Interface not declared

Wrong type

Variable not declared

Can't multiply strings

Can't redefine functions

Can't add voidNo main function

Page 8: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Wrong type

Variable not declared

Can't multiply strings

Can't redefine functions

Can't add voidNo main function

Page 9: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Wrong type

Variable not declared

Can't multiply strings

Can't add voidNo main function

Page 10: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Wrong typeCan't multiply

strings

Can't add voidNo main function

Page 11: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Review from Last Timeclass MyClass implements MyInterface { string myInteger; void doSomething() { int[] x; x = new string; x[5] = myInteger * y; } void doSomething() { } int fibonacci(int n) { return doSomething() + fibonacci(n – 1); } }

Wrong typeCan't multiply

strings

Can't add void

Page 12: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

What Remains to Check?

● Type errors.● Today:

● What are types?● What is type-checking?● A type system for Decaf.

Page 13: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

What is a Type?

● This is the subject of some debate.● To quote Alex Aiken:

● “The notion varies from language to language.

● The consensus:– A set of values.– A set of operations on those values”

● Type errors arise when operations are performed on values that do not support that operation.

Page 14: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Types of Type-Checking

● Static type checking.● Analyze the program during compile-time to prove the

absence of type errors.● Never let bad things happen at runtime.

● Dynamic type checking.● Check operations at runtime before performing them.● More precise than static type checking, but usually

less efficient.● (Why?)

● No type checking.● Throw caution to the wind!

Page 15: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Type Systems

● The rules governing permissible operations on types forms a type system.

● Strong type systems are systems that never allow for a type error.● Java, Python, JavaScript, LISP, Haskell, etc.

● Weak type systems can allow type errors at runtime.● C, C++

Page 16: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Type Wars

● Endless debate about what the “right” system is.

● Dynamic type systems make it easier to prototype; static type systems have fewer bugs.

● Strongly-typed languages are more robust, weakly-typed systems are often faster.

Page 17: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Type Wars

● Endless debate about what the “right” system is.

● Dynamic type systems make it easier to prototype; static type systems have fewer bugs.

● Strongly-typed languages are more robust, weakly-typed systems are often faster.

● I'm staying out of this!

Page 18: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Our Focus

● Decaf is typed statically and weakly:● Type-checking occurs at compile-time.● Runtime errors like dereferencing null or an

invalid object are allowed.

● Decaf uses class-based inheritance.● Decaf distinguishes primitive types and

classes.

Page 19: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Typing in Decaf

Page 20: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Static Typing in Decaf

● Static type checking in Decaf consists of two separate processes:● Inferring the type of each expression from

the types of its components.● Confirming that the types of expressions in

certain contexts matches what is expected.

● Logically two steps, but you will probably combine into one pass.

Page 21: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

}

Page 22: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

}

Page 23: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

}

Page 24: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

}

Well-typed expression with wrong type.

Page 25: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

}

Page 26: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Example

while (numBitsSet(x + 5) <= 10) {

if (1.0 + 4.0) { /* … */ }

while (5 == null) { /* … */ }

} Expression with type error

Page 27: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

Page 28: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

+

IntConstant IntConstant

137 42

Page 29: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

+

IntConstant IntConstant

137 42

int

Page 30: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

+

IntConstant IntConstant

137 42

int int

Page 31: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

+

IntConstant IntConstant

137 42

int int

int

Page 32: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

Page 33: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

=

Identifierx =

Identifiery BoolConstanttruebool bool

bool

Page 34: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

=

Identifierx =

Identifiery BoolConstanttruebool bool

boolbool

Page 35: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Inferring Expression Types

● How do we determine the type of an expression?

● Think of process as logical inference.

=

Identifierx =

Identifiery BoolConstanttruebool bool

boolbool

bool

Page 36: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Type Checking as Proofs

● We can think of syntax analysis as proving claims about the types of expressions.

● We begin with a set of axioms, then apply our inference rules to determine the types of expressions.

● Many type systems can be thought of as proof systems.

Page 37: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Sample Inference Rules

● “If x is an identifier that refers to an object of type t, the expression x has type t.”

● “If e is an integer constant, e has type int.”

● “If the operands e1 and e2 of e1 + e2 are known to have types int and int, thene1 + e2 has type int.”

Page 38: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Postconditions

Preconditions

Formalizing our Notation

● We will encode our axioms and inference rules using this syntax:

● This is read “if preconditions are true, we

can infer postconditions.”

Page 39: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Examples of Formal Notation

t ∈ FIRST(A)

A → tω is a production.

ε ∈ FIRST(A)

A → ε is a production.

t ∈ FIRST(A)

A → ω is a production.t ∈ FIRST*(ω)

ε ∈ FIRST(A)

A → ω is a production.ε ∈ FIRST*(ω)

Page 40: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Formal Notation for Type Systems

● We write

⊢ e : Tif the expression e has type T.

● The symbol ⊢ means “we can infer...”

Page 41: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Our Starting Axioms

Page 42: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Our Starting Axioms

⊢ true : bool ⊢ false : bool

Page 43: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Some Simple Inference Rules

Page 44: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

⊢ i : int

i is an integer constant

⊢ s : string

s is a string constant

Some Simple Inference Rules

⊢ d : double

d is a double constant

Page 45: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

More Complex Inference Rules

Page 46: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

More Complex Inference Rules

⊢ e1 + e2 : int

⊢ e1 : int

⊢ e2 : int

⊢ e1 + e2 : double

⊢ e1 : double

⊢ e2 : double

Page 47: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

More Complex Inference Rules

⊢ e1 + e2 : int

⊢ e1 : int

⊢ e2 : int

⊢ e1 + e2 : double

⊢ e1 : double

⊢ e2 : double

If we can show that e1 and e2 have type int…

Page 48: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

More Complex Inference Rules

⊢ e1 + e2 : int

⊢ e1 : int

⊢ e2 : int

⊢ e1 + e2 : double

⊢ e1 : double

⊢ e2 : double

If we can show that e1 and e2 have type int…

… then we can show that e1 + e2 has type int as well

Page 49: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Even More Complex Inference Rules

Page 50: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Even More Complex Inference Rules

⊢ e1 == e2 : bool

⊢ e1 : T

⊢ e2 : T

T is a primitive type

⊢ e1 != e2 : bool

⊢ e1 : T

⊢ e2 : T

T is a primitive type

Page 51: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Why Specify Types this Way?

● Gives a rigorous definition of types independent of any particular implementation.● No need to say “you should have the same type rules as my

reference compiler.”

● Gives maximum flexibility in implementation.● Can implement type-checking however you want, as long as you

obey the rules.

● Allows formal verification of program properties.● Can do inductive proofs on the structure of the program.

● This is what's used in the literature.● Good practice if you want to study types.

Page 52: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Problem

Page 53: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Problem

⊢ x : ??

x is an identifier.

Page 54: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Problem

⊢ x : ??

x is an identifier.

How do we know the type of x if we don't know what it refers to?

Page 55: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

Page 56: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

⊢ x : T

x is an identifier.x is in scope with type T.

Page 57: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

⊢ x : T

x is an identifier.x is in scope with type T.

Page 58: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts

⊢ x : T

x is an identifier.x is in scope with type T.

Page 59: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts

⊢ x : T

x is an identifier.x is in scope with type T.

Page 60: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double⊢ x : double

⊢ x : T

x is an identifier.x is in scope with type T.

Page 61: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double⊢ x : double

⊢ x : T

x is an identifier.x is in scope with type T.

Page 62: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ x : T

x is an identifier.x is in scope with type T.

Page 63: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ x : T

x is an identifier.x is in scope with type T.

Page 64: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

⊢ x : T

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

x is an identifier.x is in scope with type T.

⊢ d : double

d is a double constant

Page 65: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

⊢ x : T

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

x is an identifier.x is in scope with type T.

⊢ d : double

d is a double constant

⊢ 1.5 : double

Page 66: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

⊢ x : T

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

x is an identifier.x is in scope with type T.

⊢ 1.5 : double

Page 67: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ 1.5 : double

⊢ x : T

x is an identifier.x is in scope with type T.

Page 68: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ 1.5 : double

⊢ x : T

x is an identifier.x is in scope with type T.

⊢ e1 == e2 : bool

⊢ e1 : T

⊢ e2 : T

T is a primitive type

Page 69: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ 1.5 : double

⊢ x : T

x is an identifier.x is in scope with type T.

⊢ e1 == e2 : bool

⊢ e1 : T

⊢ e2 : T

T is a primitive type

⊢ x == 1.5 : bool

Page 70: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

An Incorrect Solution

int MyFunction(int x) { { double x; }

if (x == 1.5) { /* … */ }}

Facts⊢ x : double

⊢ x : int

⊢ 1.5 : double

⊢ x : T

x is an identifier.x is in scope with type T.

⊢ e1 == e2 : bool

⊢ e1 : T

⊢ e2 : T

T is a primitive type

⊢ x == 1.5 : bool

Page 71: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Strengthening our Inference Rules

● The facts we're proving have no context.● We need to strengthen our inference

rules to remember under what circumstances the results are valid.

Page 72: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Adding Scope

● We write

S ⊢ e : Tif, in scope S, expression e has type T.

● Types are now proven relative to the scope they are in.

Page 73: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Old Rules Revisited

S ⊢ true : bool S ⊢ false : bool

S ⊢ i : int

i is an integer constant

S ⊢ s : string

s is a string constant

S ⊢ d : double

d is a double constant

S ⊢ e1 + e2 : int

S ⊢ e1 : int

S ⊢ e2 : int

S ⊢ e1 + e2 : double

S ⊢ e1 : double

S ⊢ e2 : double

Page 74: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Correct Rule

S ⊢ x : T

x is an identifier.x is a variable in scope S with type T.

Page 75: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Correct Rule

S ⊢ x : T

x is an identifier.x is a variable in scope S with type T.

Page 76: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : ??

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 77: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : ??

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 78: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : ??

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 79: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : ??

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 80: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : ??

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 81: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : U

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Page 82: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Functions

S ⊢ f(e1, ..., en) : U

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : T

i for 1 ≤ i ≤ n

Read rules like this

Page 83: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rules for Arrays

S ⊢ e1[e2] : T

S e⊢1 : T[]

S e⊢2 : int

Page 84: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rule for Assignment

S ⊢ e1 = e2 : T

S e⊢1 : T

S e⊢2 : T

Page 85: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rule for Assignment

S ⊢ e1 = e2 : T

S e⊢1 : T

S e⊢2 : T

Why isn't this rule a problem for this statement?

5 = x;

Page 86: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Rule for Assignment

S ⊢ e1 = e2 : T

S e⊢1 : T

S e⊢2 : T

If Derived extends Base, will this rule work for this code?

Base myBase;Derived myDerived;

myBase = myDerived;

Page 87: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Typing with Classes

● How do we factor inheritance into our inference rules?

● We need to consider the shape of class hierarchies.

Page 88: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Single Inheritance

Instructor

LecturerProfessor TA

Keith JinchaoAlexAiken

Animal

Man Bear Pig

Page 89: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Multiple Inheritance

Animal

Man Bear Pig

ManBearPig

Instructor

LecturerProfessor TA

Keith JinchaoAlexAiken

Page 90: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Properties of Inheritance Structures

● Any type is convertible to itself. (reflexivity)● If A is convertible to B and B is convertible to

C, then A is convertible to C. (transitivity)● If A is convertible to B and B is convertible to

A, then A and B are the same type. (antisymmetry)

● This defines a partial order over types.

Page 91: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Types and Partial Orders

● We say that A ≤ B if A is convertible to B.● We have that

● A ≤ A● A ≤ B and B ≤ C implies A ≤ C● A ≤ B and B ≤ A implies A = B

Page 92: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : ??

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 93: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : ??

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 94: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : ??

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 95: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : T1

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 96: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : T1

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Can we do better than this?

Page 97: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Assignment

S ⊢ e1 = e2 : T2

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 98: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Not required in your semantic analyzer, but easy

extra credit!

Updated Rule for Assignment

S ⊢ e1 = e2 : T2

S e⊢1 : T

1

S e⊢2 : T

2

T2 ≤ T

1

Page 99: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

Page 100: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

Page 101: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 and T

2 are of class type.

T1 ≤ T

2 or T

2 ≤ T

1

Page 102: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 and T

2 are of class type.

T1 ≤ T

2 or T

2 ≤ T

1

Can we unify these rules?

Page 103: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

The Shape of Types

Engine

DieselEngineCarEngine

DieselCarEngine

Page 104: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

The Shape of Types

Engine

DieselEngineCarEngine

DieselCarEngine

bool string doubleint

Page 105: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

The Shape of Types

Engine

DieselEngineCarEngine

DieselCarEngine

bool string doubleintArrayTypes

Page 106: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Extending Convertibility

● If A is a primitive or array type, A is only convertible to itself.

● More formally, if A and B are types and A is a primitive or array type:● A ≤ B implies A = B● B ≤ A implies A = B

Page 107: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 and T

2 are of class type.

T1 ≤ T

2 or T

2 ≤ T

1

Page 108: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 and T

2 are of class type.

T1 ≤ T

2 or T

2 ≤ T

1

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 109: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Comparisons

S ⊢ e1 == e2 : bool

S e⊢1 : T

S e⊢2 : T

T is a primitive type

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 and T

2 are of class type.

T1 ≤ T

2 or T

2 ≤ T

1

S ⊢ e1 == e2 : bool

S e⊢1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 110: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Updated Rule for Function Calls

S ⊢ f(e1, ..., en) : U

f is an identifier.f is a non-member function in scope S.

f has type (T1, …, T

n) → U

S e⊢i : R

i for 1 ≤ i ≤ n

Ri ≤ T

i for 1 ≤ i ≤ n

Page 111: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Tricky Case

S ⊢ null : ??

Page 112: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Back to the Drawing Board

Engine

DieselEngineCarEngine

DieselCarEngine

bool string doubleintArrayTypes

Page 113: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Back to the Drawing Board

Engine

DieselEngineCarEngine

DieselCarEngine

bool string doubleintArrayTypes

null Type

Page 114: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Handling null

● Define a new type corresponding to the type of the literal null; call it “null type.”

● Define null type ≤ A for any class type A.

● The null type is (typically) not accessible to programmers; it's only used internally.

● Many programming languages have types like these.

Page 115: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Tricky Case

S ⊢ null : ??

Page 116: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Tricky Case

S ⊢ null : null type

Page 117: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Tricky Case

S ⊢ null : null type

Page 118: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Object-Oriented Considerations

S ⊢ new T : T

T is a class type.

S ⊢ NewArray(e, T) : T[]

S ⊢ e : int

S ⊢ this : T

S is in scope of class T.

Page 119: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Object-Oriented Considerations

S ⊢ new T : T

T is a class type.

S ⊢ NewArray(e, T) : T[]

S ⊢ e : int

Why don't we need to check if

T is void?

S ⊢ this : T

S is in scope of class T.

Page 120: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

What's Left?

● We're missing a few language constructs:● Member functions.● Field accesses.● Miscellaneous operators.

● Good practice to fill these in on your own.

Page 121: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Typing is Nuanced

● The ternary conditional operator ? : evaluates an expression, then produces one of two values.

● Works for primitive types:● int x = random()? 137 : 42;

● Works with inheritance:● Base b = isB? new Base : new Derived;

● What might the typing rules look like?

Page 122: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : ??

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 123: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : ??

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 124: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : ??

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 125: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : ??

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 126: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 127: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Page 128: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Base

Derived1 Derived2

Super

Page 129: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Proposed Rule

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Is this really what we want?

Base

Derived1 Derived2

Super

Page 130: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Small Problem

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Base

Derived1 Derived2

Super

Page 131: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Small Problem

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Base

Derived1 Derived2

Base = random()? new Derived1 : new Derived2;

Super

Page 132: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Small Problem

S ⊢ cond ? e1 : e2 : max(T

1, T

2)

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T1 ≤ T

2 or T

2 ≤ T

1

Base

Derived1 Derived2

Base = random()? new Derived1 : new Derived2;

Super

Page 133: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Least Upper Bounds

● An upper bound of two types A and B is a type C such that A ≤ C and B ≤ C.

● The least upper bound of two types A and B is a type C such that:● C is an upper bound of A and B.● If C' is an upper bound of A and B, then C ≤ C'.

● When the least upper bound of A and B exists, we denote it A ∨ B.● (When might it not exist?)

Page 134: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Better Rule

S ⊢ cond ? e1 : e2 : T

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T = T1 ∨ T

2Base

Derived1 Derived2

Base = random()? new Derived1 : new Derived2;

Super

Page 135: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

… that still has problems

S ⊢ cond ? e1 : e2 : T

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T = T1 ∨ T

2

Base1

Derived1 Derived2

Base2

Base = random()? new Derived1 : new Derived2;

Page 136: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

… that still has problems

S ⊢ cond ? e1 : e2 : T

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T = T1 ∨ T

2

Base1

Derived1 Derived2

Base2

Base = random()? new Derived1 : new Derived2;

Page 137: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Multiple Inheritance is Messy

● Type hierarchy is no longer a tree.● Two classes might not have a least upper

bound.● Occurs C++ because of multiple

inheritance and in Java due to interfaces.● Not a problem in Decaf; there is no

ternary conditional operator.● How to fix?

Page 138: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Minimal Upper Bounds

● An upper bound of two types A and B is a type C such that A ≤ C and B ≤ C.

● A minimal upper bound of two types A and B is a type C such that:● C is an upper bound of A and B.● If C' is an upper bound of C, then it is not true that C' < C.

● Minimal upper bounds are not necessarily unique.● A least upper bound must be a minimal upper bound,

but not the other way around.

Page 139: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Correct Rule

S ⊢ cond ? e1 : e2 : T

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T is a minimal upper bound of T1 and T

2

Base1

Derived1 Derived2

Base2

Base1 = random()? new Derived1 : new Derived2;

Page 140: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

A Correct Rule

S ⊢ cond ? e1 : e2 : T

S ⊢ cond : boolS e⊢

1 : T

1

S e⊢2 : T

2

T is a minimal upper bound of T1 and T

2

Base1

Derived1 Derived2

Base2

Base1 = random()? new Derived1 : new Derived2;

Can prove both that expression has type Base1 and that expression has

type Base2.

Page 141: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

So What?

● Type-checking can be tricky.● Strongly influenced by the choice of operators in the

language.● Strongly influenced by the legal type conversions in a

language.● In C++, the previous example doesn't compile.● In Java, the previous example does compile, but the

language spec is enormously complicated.● See §15.12.2.7 of the Java Language Specification.

Page 142: Type-Checking - Stanford University...Static type checking in Decaf consists of two separate processes: Inferring the type of each expression from the types of its components. Confirming

Next Time

● Checking Statement Validity● When are statements legal?● When are they illegal?

● Practical Concerns● How does function overloading work?● How do functions interact with inheritance?