]> Joshua Wise's Git repositories - snipe.git/blobdiff - type/typechecker.sml
Fix some stupid bugs in code generation.
[snipe.git] / type / typechecker.sml
index 35d2859e214068d1597be973148db5a31541830d..06c6d89dce342aafdb9abc4ce88c3196b2573b6b 100644 (file)
@@ -10,36 +10,37 @@ signature TYPE_CHECK =
 sig
   (* prints error message and raises ErrorMsg.error if error found *)
   val typecheck : Ast.program -> Ast.program
-  val typeof : Ast.program -> Ast.vtype Symbol.table -> Mark.ext option -> Ast.exp -> Ast.vtype
+  val typeof : Ast.program -> Type.vtype Symbol.table -> Mark.ext option -> Ast.exp -> Type.vtype
 end;
 
 structure TypeChecker :> TYPE_CHECK = 
 struct
   structure A = Ast
   structure AU = AstUtils
+  structure T = Type
   
   fun typeof (tds, funcs) vars mark e =
     ( case e
       of A.Var a => (case Symbol.look vars a
                      of NONE => (ErrorMsg.error mark ("variable `"^(Symbol.name a)^"' not declared here") ; raise ErrorMsg.Error)
                       | SOME t => t)
-       | A.ConstExp _ => A.Int
+       | A.ConstExp _ => T.Int
        | A.OpExp (A.EQ, [a, b]) =>
            (case (typeof (tds, funcs) vars mark a, typeof (tds, funcs) vars mark b)
-            of (A.Int, A.Int) => A.Int (* You shall pass! *)
+            of (T.Int, T.Int) => T.Int (* You shall pass! *)
              | (a', b') =>
-                 if (A.typeeq (a', A.TNull) andalso A.castable (b', A.TNull)) orelse
-                    (A.typeeq (b', A.TNull) andalso A.castable (a', A.TNull)) orelse
-                    (A.typeeq (a', b'))
-                 then A.Int
-                 else (ErrorMsg.error mark ("incorrect types for equality opexp: " ^ A.Print.pp_type a' ^ ", " ^ A.Print.pp_type b') ; raise ErrorMsg.Error ))
+                 if (T.typeeq (a', T.TNull) andalso T.castable (b', T.TNull)) orelse
+                    (T.typeeq (b', T.TNull) andalso T.castable (a', T.TNull)) orelse
+                    (T.typeeq (a', b'))
+                 then T.Int
+                 else (ErrorMsg.error mark ("incorrect types for equality opexp:" ^ T.Print.pp_type a' ^ ", " ^ T.Print.pp_type b') ; raise ErrorMsg.Error ))
        | A.OpExp (A.NEQ, el) => typeof (tds, funcs) vars mark (A.OpExp (A.EQ, el))
        | A.OpExp (_, el) => (List.app
                               (fn e =>
                                 (case (typeof (tds, funcs) vars mark e)
-                                 of A.Int => ()
+                                 of T.Int => ()
                                   | _ => (ErrorMsg.error mark ("incorrect type for opexp; needed int") ; raise ErrorMsg.Error)))
-                              el ; A.Int)
+                              el ; T.Int)
        | A.Marked e => typeof (tds, funcs) vars (Mark.ext e) (Mark.data e)
        | A.FuncCall (i, exps) =>
          let
@@ -53,7 +54,7 @@ struct
                     else (ErrorMsg.error mark ("call to function `"^(Symbol.name i)^"' has incorrect parameter count [you must construct additional tycons]") ; raise ErrorMsg.Error)
            val () = List.app
                       (fn (t, (i, t')) =>
-                        if not (A.castable (t', t))
+                        if not (T.castable (t', t))
                         then (ErrorMsg.error mark ("parameter `"^(Symbol.name i)^"' in function call has wrong type [you must construct additional tycons]") ; raise ErrorMsg.Error)
                         else ())
                       (ListPair.zip (exptypes, fparams))
@@ -64,14 +65,14 @@ struct
          let
            val t = typeof (tds, funcs) vars mark e
            val name = case t
-                      of (A.Typedef i) => i
+                      of (T.Typedef i) => i
                        | _ => (ErrorMsg.error mark ("member operation only exists for struct types") ; raise ErrorMsg.Error)
            val s = case Symbol.look tds name
                    of SOME s => s
                     | NONE => (ErrorMsg.error mark ("undefined structure `"^(Symbol.name name)^"' in type") ; raise ErrorMsg.Error)
-           val (s, smark) = (AU.Typedef.data s, AU.Typedef.mark s)
+           val (s, smark) = (T.defdata s, T.defmark s)
            val vl = case s
-                    of A.Struct vl => vl
+                    of T.Struct vl => vl
                      | _ => raise ErrorMsg.InternalError "mark of marked typedef?"
            val t = case (List.find (fn (i', t) => (Symbol.name i = Symbol.name i')) vl)
                    of SOME (_, t) => t
@@ -83,16 +84,16 @@ struct
          let
            val t = typeof (tds, funcs) vars mark e
            val name = case t
-                      of (A.Pointer (A.Typedef i)) => i
+                      of (T.Pointer (T.Typedef i)) => i
                        | _ => (ErrorMsg.error mark ("dereference and member operation only exists for struct pointer types") ; raise ErrorMsg.Error)
            val s = case Symbol.look tds name
                    of SOME s => s
                     | NONE => (ErrorMsg.error mark ("undefined structure `"^(Symbol.name name)^"' in type") ; raise ErrorMsg.Error)
            val (s, smark) = case s
-                            of A.Struct vl => (s, NONE)
-                             | A.MarkedTypedef m => (Mark.data m, Mark.ext m)
+                            of T.Struct vl => (s, NONE)
+                             | T.MarkedTypedef m => (Mark.data m, Mark.ext m)
            val vl = case s
-                    of A.Struct vl => vl
+                    of T.Struct vl => vl
                      | _ => raise ErrorMsg.InternalError "mark of marked typedef?"
            val t = case (List.find (fn (i', t) => (Symbol.name i = Symbol.name i')) vl)
                    of SOME (_, t) => t
@@ -102,19 +103,33 @@ struct
          end
        | A.Dereference e =>
          (case typeof (tds, funcs) vars mark e
-          of (A.Pointer e') => e'
+          of (T.Pointer e') => e'
            | _ => (ErrorMsg.error mark ("cannot deference non-pointer type") ; raise ErrorMsg.Error))
        | A.ArrIndex (e, i) =>
          (case (typeof (tds, funcs) vars mark e, typeof (tds, funcs) vars mark i)
-          of (A.Array e', A.Int) => e'
-           | (_, A.Int) => (ErrorMsg.error mark ("cannot index non-array type") ; raise ErrorMsg.Error)
+          of (T.Array e', T.Int) => e'
+           | (_, T.Int) => (ErrorMsg.error mark ("cannot index non-array type") ; raise ErrorMsg.Error)
            | _ => (ErrorMsg.error mark ("cannot index using non-int type") ; raise ErrorMsg.Error))
-       | A.New (t) => A.Pointer t
+       | A.New (t) => T.Pointer t
        | A.NewArr (t, s) =>
          (case typeof (tds, funcs) vars mark s
-          of A.Int => (A.Array t)
+          of T.Int => (T.Array t)
            | _ => (ErrorMsg.error mark ("cannot specify non-int array dimension") ; raise ErrorMsg.Error))
-       | A.Null => A.TNull
+       | A.Null => T.TNull
+       | A.Conditional (q, e1, e2) =>
+         let
+           val _ = case typeof (tds, funcs) vars mark q
+                   of T.Int => ()
+                    | _ => (ErrorMsg.error mark ("ternary condition not of Int type") ; raise ErrorMsg.Error)
+           val t1 = typeof (tds, funcs) vars mark e1
+           val t2 = typeof (tds, funcs) vars mark e2
+         in
+           if (T.typeeq (t1, t2) orelse T.castable (t1, t2))
+           then t1
+           else if (T.castable (t2, t1))
+           then t2
+           else (ErrorMsg.error mark ("ternary types do not agree [you must construct additional tycons]") ; raise ErrorMsg.Error)
+         end
     )
   
   datatype asn = ASSIGNED | UNASSIGNED
@@ -131,7 +146,7 @@ struct
         | returns' (A.AsnOp _ :: stms) = returns' stms
         | returns' (A.Effect _ :: stms) = returns' stms
         | returns' (A.Return e :: stms) =
-            if (A.castable (t, typeof prog vars mark e))
+            if (T.castable (t, typeof prog vars mark e))
             then true
             else (ErrorMsg.error mark ("return value of incorrect type for function") ; raise ErrorMsg.Error)
         | returns' (A.Nop :: stms) = returns' stms
@@ -202,6 +217,7 @@ struct
     | varcheck_exp env (A.New _) mark = ()
     | varcheck_exp env (A.NewArr (_, e)) mark = varcheck_exp env e mark
     | varcheck_exp env (A.Null) mark = ()
+    | varcheck_exp env (A.Conditional (q, e1, e2)) mark = (varcheck_exp env q mark ; varcheck_exp env e1 mark ; varcheck_exp env e2 mark)
   
   (* computeassigns env exp
    * Computes the assigned variables after expression exp has been executed with a starting context of env.
@@ -285,7 +301,7 @@ struct
          varcheck_exp env e mark ;
          a :: varcheck env stms mark)
     | varcheck env ((A.Assign _) :: stms) mark = raise ErrorMsg.InternalError "assign to non lvalue"
-    | varcheck env ((a as A.AsnOp (oper, e1, e2)) :: stms) mark = ( varcheck env [(A.Assign (e1, A.OpExp (oper, [e1, e2])))] ; a :: varcheck env stms mark)
+    | varcheck env ((a as A.AsnOp (oper, e1, e2)) :: stms) mark = ( varcheck_exp env e1 mark ; varcheck_exp env e2 mark ; a :: varcheck env stms mark )
     | varcheck env ((a as A.Effect e) :: stms) mark = (varcheck_exp env e mark ; a :: varcheck env stms mark)
     | varcheck env (A.Return (e) :: stms) mark =
         ( varcheck_exp env e mark;
@@ -320,7 +336,7 @@ struct
           val env' = case sbegin
                      of SOME(s) => computeassigns env [s]
                       | NONE => env
-          val _ = varcheck_exp env' e
+          val _ = varcheck_exp env' e mark
           val inner = varcheck env' inner mark
           val env'' = computeassigns env' inner
           val sloop = case sloop
@@ -358,14 +374,14 @@ struct
   fun typecheck_stm prog vars mark stm =
     case stm
     of A.Assign (e1, e2) =>
-         if not (A.castable (check_lvalue prog vars mark e1, typeof prog vars mark e2))
+         if not (T.castable (check_lvalue prog vars mark e1, typeof prog vars mark e2))
          then (ErrorMsg.error mark "incompatible types in assignment" ; raise ErrorMsg.Error )
-         else if not (AU.Type.issmall (check_lvalue prog vars mark e1))
+         else if not (T.issmall (check_lvalue prog vars mark e1))
          then (ErrorMsg.error mark "lvalue is not small" ; raise ErrorMsg.Error)
          else ()
      | A.AsnOp (oper, e1, e2) => typecheck_stm prog vars mark (A.Assign (e1, A.OpExp (oper, [e1, e2])))
      | A.Effect e => 
-         if not (AU.Type.issmall (typeof prog vars mark e))
+         if not (T.issmall (typeof prog vars mark e))
          then (ErrorMsg.error mark "simple statement's value not small" ; raise ErrorMsg.Error )
          else ()
      | A.Return e => (typeof prog vars mark e ; ())
@@ -373,36 +389,36 @@ struct
      | A.Break => ()
      | A.Continue => ()
      | A.If (e, s, NONE) =>
-         if A.castable (A.Int, typeof prog vars mark e)
+         if T.castable (T.Int, typeof prog vars mark e)
          then (List.app (typecheck_stm prog vars mark) s)
          else (ErrorMsg.error mark "conditional in if statement is not of int type" ; raise ErrorMsg.Error )
      | A.If (e, s1, SOME s2) =>
-         if A.castable (A.Int, typeof prog vars mark e)
+         if T.castable (T.Int, typeof prog vars mark e)
          then (List.app (typecheck_stm prog vars mark) s1 ; List.app (typecheck_stm prog vars mark) s2)
          else (ErrorMsg.error mark "conditional in if statement is not of int type" ; raise ErrorMsg.Error )
      | A.For (sbegin, e, sloop, s) =>
-         if A.castable (A.Int, typeof prog vars mark e)
+         if T.castable (T.Int, typeof prog vars mark e)
          then (List.app (typecheck_stm prog vars mark) ((case sbegin of SOME l => [l] | NONE => nil) @ (case sloop of SOME l => [l] | NONE => nil) @ s))
          else (ErrorMsg.error mark "conditional in for statement is not of int type" ; raise ErrorMsg.Error )
      | A.While (e, s) =>
-         if A.castable (A.Int, typeof prog vars mark e)
+         if T.castable (T.Int, typeof prog vars mark e)
          then (List.app (typecheck_stm prog vars mark) s)
          else (ErrorMsg.error mark "conditional in while statement is not of int type" ; raise ErrorMsg.Error )
      | A.MarkedStm (m) => typecheck_stm prog vars (Mark.ext m) (Mark.data m)
         
   (* XXX does not check big vs. small types *)
-  fun typecheck_type (tds, funcs) mark A.Int = ()
-    | typecheck_type (tds, funcs) mark A.TNull = ()
-    | typecheck_type (tds, funcs) mark (A.Pointer t) = typecheck_type (tds, funcs) mark t
-    | typecheck_type (tds, funcs) mark (A.Array t) = typecheck_type (tds, funcs) mark t
-    | typecheck_type (tds, funcs) mark (A.Typedef t) =
+  fun typecheck_type (tds, funcs) mark T.Int = ()
+    | typecheck_type (tds, funcs) mark T.TNull = ()
+    | typecheck_type (tds, funcs) mark (T.Pointer t) = typecheck_type (tds, funcs) mark t
+    | typecheck_type (tds, funcs) mark (T.Array t) = typecheck_type (tds, funcs) mark t
+    | typecheck_type (tds, funcs) mark (T.Typedef t) =
         case (Symbol.look tds t)
         of SOME _ => ()
          | NONE => (ErrorMsg.error mark ("typedef `"^(Symbol.name t)^"' does not exist") ; raise ErrorMsg.Error)
 
   fun typecheck_fn prog _ (id, A.MarkedFunction m) = typecheck_fn prog (Mark.ext m) (id, Mark.data m)
     | typecheck_fn (prog as (tds, funcs)) mark (id, A.Extern (t, al)) =
-      (if (String.isPrefix "_l4_" (Symbol.name id))
+      (if (String.isPrefix "_l5_" (Symbol.name id))
        then
          let
            val n = String.extract (Symbol.name id, 4, NONE)
@@ -432,7 +448,7 @@ struct
                  else ()
         val () = List.app (
                   fn (n, t) =>
-                    if (AU.Type.issmall t)
+                    if (T.issmall t)
                     then ()
                     else ( ErrorMsg.error mark ("variable `"^(Symbol.name n)^"' in function `"^(Symbol.name id)^"' not small") ; raise ErrorMsg.Error))
                  (al @ vl)
@@ -458,11 +474,11 @@ struct
           val s = case Symbol.look tds sym
                   of SOME a => a
                    | NONE => (ErrorMsg.error mark ("typedef `"^(Symbol.name sym)^"' does not exist") ; raise ErrorMsg.Error)
-          val vl = case AU.Typedef.data s
-                   of A.Struct vl => vl
-                    | A.MarkedTypedef v => raise ErrorMsg.InternalError "data returned marked type"
+          val vl = case T.defdata s
+                   of T.Struct vl => vl
+                    | T.MarkedTypedef v => raise ErrorMsg.InternalError "data returned marked type"
         in
-          (vl, AU.Typedef.mark s)
+          (vl, T.defmark s)
         end
       fun checksym mark sym stack k remaining =
         if not (SymbolSet.member (remaining, sym))
@@ -477,7 +493,7 @@ struct
             fun remove k remaining' = k (SymbolSet.delete (remaining', sym))
             val newk = (* OH GOD D: *)
               foldr
-                (fn ((_, A.Typedef s), k') => checksym mark' s stack' k'
+                (fn ((_, T.Typedef s), k') => checksym mark' s stack' k'
                   | (_, k') => k')
                 (remove k)
                 vl
@@ -502,8 +518,8 @@ struct
         val () = case main
                  of A.Extern _ => ( ErrorMsg.error mainp ("you anus, main can't be an extern");
                                     raise ErrorMsg.Error )
-                  | A.Function (A.Int, nil, _, _) => ()
-                  | A.Function (A.Int, _, _, _) => ( ErrorMsg.error mainp ("main should take no parameters");
+                  | A.Function (T.Int, nil, _, _) => ()
+                  | A.Function (T.Int, _, _, _) => ( ErrorMsg.error mainp ("main should take no parameters");
                                                         raise ErrorMsg.Error )
                   | A.Function (_, _, _, _) => ( ErrorMsg.error mainp ("main has incorrect return type");
                                                  raise ErrorMsg.Error )
This page took 0.039356 seconds and 4 git commands to generate.