Soundness Theorem: for all expression E,
dynamic_type(E) = static_type(E)
(if no inheritance)
for all E
, dynamic_type(E) <= static_type(E)
(if inheritance, one consequence is that you can only add methods to children types and can only override methods without changing its type)
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.
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
\text{SELF\_TYPE}_C \leq \text{SELF\_TYPE}_C
\text{SELF\_TYPE}_C \leq T if C \leq T
T \leq \text{SELF\_TYPE}_C is always false (because T might not be the child of child of C)
\text{lub}(T, \text{SELF\_TYPE}_C) = \text{lub}(C, T)
SELF_TYPE
appear
cannot write class SELF_TYPE inherits T {...}
cannot write class T inherits SELF_TYPE {...}
can write X : SELF_TYPE
can write let x : SELF_TYPE in E
can write new : SELF_TYPE
(create an object that has same dynamic type of self
)
cannot write [email protected]_TYPE(E1, ..., En)
can write m(x : T) : SELF_TYPE {...}
cannot write m(x : SELF_TYPE) : SELF_TYPE {...}
To see why the last statement is true, consider the following code:
Note that the return type is
T0
notT
in static dispatch.
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.
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