COS 320 March 7, 2006; Lecture 9

advertisement
COS 320
March 7, 2006; Lecture 9
MinML (same definition as last lecture)
Types t ::= int | bool | T1  T2
Expressions e ::= x | n | o(e e) | true | false | if e then e else e | fun f (x:T1):T2 = e | e
Ops o ::= + | < | - | *
Integers n
Γ |- e : T “In context Γ, e is well-typed and produces a value with type T”
Γ  function from variables to types
Γ [x:t]  is a new context
Γ(x) = T “look-up in the context”
Goal is to have typing rules defined to prevent the following kinds of errors when
executing a program, (should never run into the situation in which it is necessary to do
one of the following things).
1) Apply something that isn’t a value. Eg “3 e” or (where x is not a function) “x e”
2) Never execute “if V then…” where V is not a Boolean
3) Never apply a built-in operator to the wrong kind of argument
(note, I’m using  in place of |- )
  e1 : int
  e2 : int
  n : int
  e1  e2 : int
  e1 : int
  e2 : int
Basic Boolean typing:
  true : bool   false : bool
  e1  e2 : bool
[ x : T1][f : T1  T2]  e : T2
Function definition
(note that on top we don’t
  fun f (x : T1) : T2  e : T1  T2
check x:T1)
x  dom() and T  ( x)
or
  x : ( x )
  x : ( x )
Basic integer typing:
  e1 : T1  T2   e2 : T1
  e1 e2
If statements (note that if e2 and e3 don’t share their types then it isn’t possible to
  e1 : bool   e2 : T   e2 : T
determine at compile time the type of the if)
  if e1 then e2 else e3 : T
Another property of our MinML rules: given a context Γ and e, either there exists a
unique type T such that the judgement Γ|-e:T or e does not type check (proof by
induction…take COS 441 if this is your sort of thing)  type checking is syntax-directed.
(this is not the case in all languages…eg in ML, the statement “let fun id x = x”).
Factorial function
  x : int   1 : int
  fact : int  int
  (x - 1) : int
  fact ( x  1) : int
  x : int   1 : int
  x  1 : bool
  1 : int
  fact ( x  1) * x : 1 : int
[fact : int  int][ x : int]  if x  1 then 1 else fact (x - 1) * x : int
.  fun fact (x : int) : int  if x  1 then 1 else (fact (x - 1)) * x : int
  x : int
In a nutshell: the algorithm for type checking according to the MinML rules is:
Given Inputs: Context Γ and Expression e.
1) Identify the typing rule (by looking at e)
2) Recursively compute the types of the subexpressions.
3) Check constraints in rules and return the type of whole expression.
Now, since Professor Walker likes to mess with us…
Subtyping
Add to types T “float”, add to expressions e “f”, add to ops o “+.”
Define int  float
“  ” = “is a subtype”
Type T1 is a subtype of type T2 only if all values with type T1 count as values of type T2.
Every operation that handles arguments with type T2 also must handle arguments with
type T1.
Adding two new rules then
  e1 : float
  e2 : float
  e1 : T1 T1  T2
“+.”
and “subsumption”
  e1  . e2 : float
  e1 : T2
Now say you define int  intint…then you can say
 0 : int
int  int  int
 17 : int
 0 : int  int
this is bad, ‘nuff sed so we have to be careful
 0 17 : int
when selecting / subtyping rules (or really any of the rules).
More extensions of MinML (moving towards ML / Fun)
Add to e “(e1, …, en) | #i e”
Add to T “T1 * ... * Tn”
Type rules for tuples / projs
  e1 : T1 ...   e2 : Tn
  e : T1 * ... * Tn
and (1  i  n)
  # i e : Ti
  (e1 ,..., en ) : T1 * ... * Tn
k m
T1 * ... * Tk  T1 * ... * Tm
(if you do the converse and say k can be < m, then you can say something like int * int 
int * int * int, and so if you try doing “#3” on something of type int * int, then it will be
considered safe when it really should crash / not be allowed).
Adding subtyping results in the loss of the property that every expression only has one
type.
Download