Table of Contents
This chapter is work in progress. Not all parts have been finished yet. The latest revision of this manual may contain more material. Refer to the online version.
propagation of variable types and type annotation of expressions and statements
Figure 5.1. file: til/tc/til-typecheck.str
module til-typecheck
imports liblib til-typecheck-stats
strategies
io-til-typecheck =
io-wrap(typecheck-program)
typecheck-program =
Program(typecheck-stats)
Figure 5.2. file: til/tc/til-typecheck-exp.str
module til-typecheck-exp
imports TIL
strategies
typecheck-exp(typecheck-var) =
bottomup(try(
typecheck-var <+ TypecheckAdd <+ TypecheckMul <+ TypecheckSub <+ TypecheckDiv <+ TypecheckMod
<+ TypecheckLeq <+ TypecheckGeq <+ TypecheckLt <+ TypecheckGt <+ TypecheckEqu <+ TypecheckNeq
<+ TypecheckOr <+ TypecheckAnd
<+ TypecheckInt <+ TypecheckString <+ TypecheckBool
))
rules
typeof :
e{t*} -> t
where <fetch-elem(is-type)> t* => t
is-type =
?TypeName(_)
TypecheckInt :
Int(i) -> Int(i){TypeName("int")}
TypecheckString :
String(x) -> String(x){TypeName("string")}
TypecheckBool :
True() -> True(){TypeName("bool")}
TypecheckBool :
False() -> False(){TypeName("bool")}
TypecheckAdd :
Add(e1, e2) -> Add(e1, e2){TypeName("string")}
where <typeof> e1 => TypeName("string")
; <typeof> e2 => TypeName("string")
TypecheckAdd :
Add(e1, e2) -> Add(e1, e2){TypeName("int")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckMul :
Mul(e1, e2) -> Mul(e1, e2){TypeName("int")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckSub :
Sub(e1, e2) -> Sub(e1, e2){TypeName("int")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckDiv :
Div(e1, e2) -> Div(e1, e2){TypeName("int")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckMod :
Mod(e1, e2) -> Mod(e1, e2){TypeName("int")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckLt :
Lt(e1, e2) -> Lt(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckGt :
Gt(e1, e2) -> Gt(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckLeq :
Leq(e1, e2) -> Leq(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckGeq :
Geq(e1, e2) -> Geq(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckEqu :
Equ(e1, e2) -> Equ(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckNeq :
Neq(e1, e2) -> Neq(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
TypecheckAnd :
And(e1, e2) -> And(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("bool")
; <typeof> e2 => TypeName("bool")
TypecheckOr :
Or(e1, e2) -> Or(e1, e2){TypeName("bool")}
where <typeof> e1 => TypeName("bool")
; <typeof> e2 => TypeName("bool")
Figure 5.3. file: til/tc/til-typecheck-stats.str
module til-typecheck-stats
imports til-typecheck-var
strategies
typecheck-block =
Block(typecheck-stats)
typecheck-stats =
{| TypeOf : map(typecheck-stat) |}
typecheck-stat =
typecheck-block
<+ typecheck-declaration
<+ Assign(id, typecheck-exp)
; try(TypecheckAssign)
<+ IfElse(typecheck-exp, typecheck-stats, typecheck-stats)
; TypecheckIf
<+ IfThen(typecheck-exp, typecheck-stats)
; TypecheckIf
<+ While(typecheck-exp, typecheck-stats)
; TypecheckWhile
<+ ProcCall(id, map(typecheck-exp))
; typecheck-proccall
<+ For(id, typecheck-exp, typecheck-exp, typecheck-stats)
; TypecheckFor
<+ debug(!"unknown statement: ")
; <exit> 1
TypecheckIf :
IfElse(e, st1*, st2*) -> IfElse(e, st1*, st2*){TypeName("void")}
where <typeof> e => TypeName("bool")
TypecheckIf :
IfThen(e, st*) -> IfThen(e, st*){TypeName("void")}
where <typeof> e => TypeName("bool")
TypecheckWhile :
While(e, st*) -> While(e, st*){TypeName("void")}
where <typeof> e => TypeName("bool")
TypecheckFor :
For(x, e1, e2, st*) -> For(x, e1, e2, st*){TypeName("void")}
where <TypeOf> x => TypeName("int")
; <typeof> e1 => TypeName("int")
; <typeof> e2 => TypeName("int")
Figure 5.4. file: til/tc/til-typecheck-var.str
module til-typecheck-var
imports til-typecheck-exp
strategies
typecheck-declaration =
?Declaration(x)
; rules( TypeOf+x : x -> TypeName("int") )
typecheck-declaration =
?DeclarationTyped(x, t)
; rules( TypeOf+x : x -> t )
TypecheckVar :
Var(x) -> Var(x){t}
where <TypeOf> x => t
TypecheckAssign :
Assign(x, e) -> Assign(x, e){TypeName("void")}
where <typeof> e => t
; <TypeOf> x => t
strategies // expressions with variables and calls
typecheck-exp =
typecheck-exp(TypecheckVar <+ typecheck-funcall)
typecheck-funcall =
TypecheckRead <+ TypecheckS2I <+ TypecheckI2S <+ TypecheckB2S
typecheck-proccall =
TypecheckWrite
strategies // built-in functions
TypecheckS2I :
FunCall("string2int", [e]) -> FunCall("string2int", [e]){TypeName("int")}
where <typeof> e => TypeName("string")
TypecheckI2S :
FunCall("int2string", [e]) -> FunCall("int2string", [e]){TypeName("string")}
where <typeof> e => TypeName("int")
TypecheckB2S :
FunCall("bool2string", [e]) -> FunCall("bool2string", [e]){TypeName("string")}
where <typeof> e => TypeName("bool")
TypecheckRead :
FunCall("read", []) -> FunCall("read", []){TypeName("string")}
TypecheckRead :
FunCall("readint", []) -> FunCall("readint", []){TypeName("int")}
strategies // built-in procedures
TypecheckWrite :
ProcCall("write", [e]) -> ProcCall("write", [e]){TypeName("void")}
where <typeof> e => TypeName("string")
TypecheckWrite :
ProcCall("writeint", [e]) -> ProcCall("writeint", [e]){TypeName("void")}
where <typeof> e => TypeName("int")
Figure 5.5. file: til/xmpl/typecheck-test1
# typecheck test1.til after parsing ../tc/til-typecheck -i test1.atil | pp-aterm > test1.tc
Table 5.1. files: til/xmpl/test1.til, til/xmpl/test1.tc
| before | after |
|---|---|
// TIL program computing the factorial
var n;
n := readint();
var x;
var fact;
fact := 1;
for x := 1 to n do
fact := x * fact;
end
write("factorial of ");
writeint(n);
write(" is ");
writeint(fact);
write("\n");
| Program(
[ Declaration("n")
, Assign("n", FunCall("readint", []){TypeName("int")}){TypeName("void")}
, Declaration("x")
, Declaration("fact")
, Assign("fact", Int("1"){TypeName("int")}){TypeName("void")}
, For(
"x"
, Int("1"){TypeName("int")}
, Var("n"){TypeName("int")}
, [Assign("fact", Mul(Var("x"){TypeName("int")}, Var("fact"){TypeName("int")}){TypeName("int")}){TypeName("void")}]
){TypeName("void")}
, ProcCall("write", [String("\"factorial of \""){TypeName("string")}]){TypeName("void")}
, ProcCall("writeint", [Var("n"){TypeName("int")}]){TypeName("void")}
, ProcCall("write", [String("\" is \""){TypeName("string")}]){TypeName("void")}
, ProcCall("writeint", [Var("fact"){TypeName("int")}]){TypeName("void")}
, ProcCall("write", [String("\"\\n\""){TypeName("string")}]){TypeName("void")}
]
)
|