A Type System for SimPL
Recall the syntax of SimPL:
e ::= x | i | b | e1 bop e2
| if e1 then e2 else e3
| let x = e1 in e2
bop ::= + | * | <=
Let's define a type system ctx |- e : t
for SimPL.
The only types in SimPL are integers and booleans:
t ::= int | bool
To define |-
, we'll invent a set of typing rules that specify what
the type of an expression is based on the types of its subexpressions.
In other words, |-
is an inductively-defined relation, as you
learned about in CS 2800. So, it has some base cases, and some
inductive cases.
Base Cases
An integer constant has type int
in any context whatsoever,
a Boolean constant likewise always has type bool
, and a
variable has whatever type the context says it
should have. Here are the typing rules that express those ideas:
ctx |- i : int
ctx |- b : bool
{x : t, ...} |- x : t
Inductive Cases
Let. As we already know from OCaml, we type check the body of a let expression using a scope that is extended with a new binding.
ctx |- let x = e1 in e2 : t2
if ctx |- e1 : t1
and ctx[x -> t1] |- e2 : t2
The rule says that let x = e1 in e2
has type t2
in context ctx
, but
only if certain conditions hold. The first condition is that
e1
has type t1
in ctx
. The second is that e2
has type t2
in a new context, which is ctx
extended to bind x
to t1
.
Binary operators. We'll need a couple different rules for binary operators.
ctx |- e1 bop e2 : int
if bop is + or *
and ctx |- e1 : int
and ctx |- e2 : int
ctx |- e1 <= e2 : bool
if ctx |- e1 : int
and ctx |- e2 : int
If. Just like OCaml, an if expression must have a Boolean guard, and its two branches must have the same type.
ctx |- if e1 then e2 else e3 : t
if ctx |- e1 : bool
and ctx |- e2 : t
and ctx |- e3 : t