3 * Author: Alex Vaynberg <alv@andrew.cmu.edu>
4 * Modified: Frank Pfenning <fp@cs.cmu.edu>
6 * Simple typechecker that is based on a unit Symbol.table
7 * This is all that is needed since there is only an integer type present
10 signature TYPE_CHECK =
12 (* prints error message and raises ErrorMsg.error if error found *)
13 val typecheck : Ast.program -> unit
16 structure TypeChecker :> TYPE_CHECK =
20 (* tc_exp : unit Symbol.table -> Ast.exp -> Mark.ext option -> unit *)
21 fun tc_exp env (A.Var(id)) ext =
22 (case Symbol.look env id
23 of NONE => ( ErrorMsg.error ext ("undefined variable `" ^ Symbol.name id ^ "'") ;
24 raise ErrorMsg.Error )
26 | tc_exp env (A.ConstExp(c)) ext = ()
27 | tc_exp env (A.OpExp(oper,es)) ext =
28 (* Note: it is syntactically impossible in this language to
29 * apply an operator to an incorrect number of arguments
30 * so we only check each of the arguments
32 List.app (fn e => tc_exp env e ext) es
33 | tc_exp env (A.Marked(marked_exp)) ext =
34 tc_exp env (Mark.data marked_exp) (Mark.ext marked_exp)
36 (* tc_stms : unit Symbol.table -> Ast.program -> unit *)
37 fun tc_stms env nil = ()
38 | tc_stms env (A.Assign(id,e)::stms) =
40 tc_stms (Symbol.bind env (id, ())) stms )
41 | tc_stms env (A.Return(e)::nil) =
43 | tc_stms env (A.Return _ :: _) =
44 ( ErrorMsg.error NONE ("`return' not last statement") ;
45 raise ErrorMsg.Error )
47 fun typecheck prog = tc_stms Symbol.empty prog