Lecture 010

Static and Dynamic Typing

Soundness Theorem: for all expression E,

Dynamic Typing: one symbol can be different types at different time during the execution of the program.

A symbol will have both a static type that is decided at compile time and a dynamic type that is decided at runtime.

Self-Type

Consider the following code

class Count {
  i : int <- 0;
  int () : Count {
    {
      i <- i + 1;
      self;
    }
  }
}

class Stock inherits Count {
  name : String;
}

class Main {
  Stock a <- (new Stock).inc()
}

In above code, when (new Stock).inc() is run, it return an object that has static type Count and not the type Stock. Therefore this line will not type check although the dynamic type is correct. We can fix this issue by letting .inc() return a SELF_TYPE.

SELF_TYPE is a static type and not a class name

If a SELF_TYPE appear in the Class C, then we can say \text{SELF\_TYPE}_C \leq C

Rules for SELF_TYPE

SELF_TYPE appear

To see why the last statement is true, consider the following code:

This function will result a type error at runtime.

This function will result a type error at runtime.

Updated Dispatch with no return SELF_TYPE

Updated Dispatch with no return SELF_TYPE

Update Dispatch with return SELF_TYPE

Update Dispatch with return SELF_TYPE

Updated Static Dispatch with no return SELF_TYPE

Updated Static Dispatch with no return SELF_TYPE

Update Static Dispatch with return SELF_TYPE

Update Static Dispatch with return SELF_TYPE

Note that the return type is T0 not T in static dispatch.

Error Recovery

To Recover: A simple solution might be to assign type Object to any type that is undefined or error. However, this will lead to cascading error.

Cascading Error

Cascading Error

Another method is to introduce Notype by define Notype < C for every type C and all operation is defined on Notype. So only the first error will be generated. Note that the introduction of Notype will make our type system not a tree, which will be harder to implement.

Table of Content