# Type checking II

Lecture 8

## Table of Contents

## Review

### Questions about the last class?

### Quiz

Is printf part of the C language?

### Quiz Discussion

## Is printf part of C?

- Library methods vs. keywords
- Keywords in syntax vs. reserved identifiers
- Growing a Language
- Language as methods of abstraction, adding new symbols
`-nostdinc`

flag

## Performing type checking

- Type checker proves that input an program follows the typing rules

### SimpleC's types

- int, bool, string, function

### int

- Set of integers
- What operations are there for integers?

Definition of int type vs. machine representation.

C long vs. Java BigInt

### How do we check an operation?

- Examples: addition
`+`

- Takes two integers

- How do we know 1 + 2 is legal?
`+`

takes two integers- How do we know
`1`

and`2`

's types?

Remember: the map is not the territory! The ASCII symbols for `1`

, `2`

, `+`

, are just numeric encoding conventions that our systems use to draw glyphs on screen. The type-checker needs to interpret the meaning of these symbols.

While we can easily observe the type ourselves, we need to create an program on a computer that can mechanically determine the meaning without a human to tell it our interpretation the meaning.

### Types of symbols in the language

- Integer literals (defined in syntax)
- Always have type "int" (as an axiom)

- What about variables?

Declarations give axioms/assumptions to the type-checker so it can prove

### Type-checking `1 + 2`

- We know
`+`

takes two integer - We know
`1`

and`2`

are integers - Therefore we know
`1 + 2`

is type safe. QED!

### What about `+`

in `1 + 2 * 3`

?

- We know
`+`

takes two integers? `1`

is an integer?- How do we know the type of
`2 * 3`

?

### The type of functions

`+`

is a function- We define it to take two integer
- And we define it to produce an integer
- Using formal notation:
`+ : (int, int) -> int`

The symbol `+`

is a function `->`

which takes two integer `(int, int)`

and returns an integer `-> int`

### The typing rules for functions and type operations are the same

`+`

is a built-in function with special syntax (infix instead of prefix)

### Back to `1 + 2 * 3`

- To type-checking
`+`

we need to type-check`2 * 3`

- To type-check
`*`

, we check its type`* : (int, int) -> int)`

- Type-checking a function both
- ensures its parameter types match, and
- deduces the return value's type

### Let's sketch an algorithm for type-checking arithmetic expressions

- How can we handle these nested constructs?

The typing rules implemented by the type checker are designed to match the actual runtime behavior of the program. Programming language researchers develop proofs that the type system reflects the runtime behavior and also ensures safety.

### Recursively type-check expression

- Basically an evaluator, like Calc.java
- But instead of integer values, we use a type as the (abstract) value
- Recall that a type is a set of legal values (and operators)
- Type-checking gives symbols the type name itself instead of one of the values

### Algorithm pseudo-code

typecheck(expr): if expr is NUM: return INT elif expr equals either "true" or "false": return BOOL elif expr.op is one of + - * / assert typecheck(expr.left) == INT assert typecheck(expr.right) == INT return INT elif expr.op is one of < <= > >= == != assert typecheck(expr.left) == INT assert typecheck(expr.right) == INT return BOOL elif expr.op is one of && || ! assert typecheck(expr.left) == BOOL assert typecheck(expr.right) == BOOL return BOOL

### Compare to an evaluator

- Same structure
- Different operations

eval(expr): if expr is NUM: return toInteger(expr) elif expr equals either "true" or "false": return expr == "false" ? 0 : 1 elif expr.op is one of + - * / left = eval(expr.left) right = eval(expr.right) return do_op(left, expr.op, right) elif expr.op is one of < <= > >= == != left = eval(expr.left) right = eval(expr.right) return do_op(left, expr.op, right) elif expr.op is one of && || ! left = eval(expr.left) right = eval(expr.right) return do_op(left, expr.op, right)

## Type checkers as theorem provers

- Type-checker is equivalent to logical proofs
- Curry-howard correspondence
- Coq is a proof writing assistant based on

### Function's return type is the theorem

- Type-checking proves that it returns the type
- Leaves of the tree are axioms
- Defined by language designer or by developer

### Typing judgments

- Based on "proof rules"
- Systematic notation for deriving proofs from logical rules

- Popular notation in academia
- Sort of an esoteric description of an evaluator

- Described in Type Systems
- Example

## Handling declarations

- User may add new symbols to the language
- Type-checking needs to proof type safety of these as well
- Many language require declarations

Some languages can infer types from operators used.

### Type-checker records type information about each symbol

- Maps symbol name to type
- Declarations populate the symbol table
- Relevant to scoping rules
- Same name, different memory location
- Disambiguate by scope

### Symbol tables

(Source)

## Conditional statements

x = setx() if (x > 10) y = 1 else y = "hello"

### What if the type-unsafe branch is not reachable?

x = setx() if (x > 10) y = 1 else y = "hello"

### Design decisions

- No type system: any symbol, any type
- Type-safety: values in all uses fit symbol's type
- Inflexible in C, e.g., no function overloading

### Polymorphism

- Designs that permit multiple types for the same symbol, e.g.,
- Subclasses
- Operator/function overloading
- Generics

## Type checking loops

### What if we don't know how long the loop runs?

int y int x

while x > 0 if (x > 10) y = 1 else y = "hello" x = updatex(x)