Better messages for top-level unification errors
authorAdam Chlipala <adamc@hcoop.net>
Sun, 18 Nov 2007 18:42:36 +0000 (18:42 +0000)
committerAdam Chlipala <adamc@hcoop.net>
Sun, 18 Nov 2007 18:42:36 +0000 (18:42 +0000)
src/tycheck.sml

index 8889540..def1463 100644 (file)
@@ -650,6 +650,56 @@ fun checkDecl G (d, _, loc) =
        end
       | DContext name => bindContext G name
 
        end
       | DContext name => bindContext G name
 
+fun printActionDiffs {have, need} =
+    case (ununif have, ununif need) of
+       ((TAction (p1, in1, out1), loc), (TAction (p2, in2, out2), _)) =>
+       let
+           fun checkPreds () =
+               if predImplies (p1, p2) then
+                   ()
+               else
+                   (ErrorMsg.error (SOME loc) "Files provides the wrong kind of configuration.";
+                    preface ("Have:", p_pred p1);
+                    preface ("Need:", p_pred p2))
+
+           fun checkIn () =
+               SM.appi (fn (name, t) =>
+                           case SM.find (in2, name) of
+                               NONE => (ErrorMsg.error (SOME loc) "An unavailable environment variable is used.";
+                                        print ("Name: " ^ name ^ "\n");
+                                        preface ("Type:", p_typ t))
+                             | SOME t' =>
+                               subTyp (t', t)
+                               handle Unify _ =>
+                                      (ErrorMsg.error (SOME loc) "Wrong type for environment variable.";
+                                       print ("          Name: " ^ name ^ "\n");
+                                       preface ("      Has type:", p_typ t');
+                                       preface ("Used with type:", p_typ t)))
+                       in1
+                       
+           fun checkOut () =
+               SM.appi (fn (name, t) =>
+                           case SM.find (out1, name) of
+                               NONE => (ErrorMsg.error (SOME loc) "Missing an output environment variable.";
+                                        print ("Name: " ^ name ^ "\n");
+                                        preface ("Type:", p_typ t))
+                             | SOME t' =>
+                               subTyp (t', t)
+                               handle Unify _ =>
+                                      (ErrorMsg.error (SOME loc) "Wrong type for output environment variable.";
+                                       print ("     Name: " ^ name ^ "\n");
+                                       preface (" Has type:", p_typ t');
+                                       preface ("Need type:", p_typ t)))
+                       out2
+       in
+           checkPreds ();
+           checkIn ();
+           checkOut ();
+           true
+       end
+       
+      | _ => false
+
 fun checkFile G tInit (_, ds, eo) =
     let
        val G' = foldl (fn (d, G) => checkDecl G d) G ds
 fun checkFile G tInit (_, ds, eo) =
     let
        val G' = foldl (fn (d, G) => checkDecl G d) G ds
@@ -661,10 +711,11 @@ fun checkFile G tInit (_, ds, eo) =
                val t = checkExp G' e
            in
                hasTyp (e, t, tInit)
                val t = checkExp G' e
            in
                hasTyp (e, t, tInit)
-               handle Unify ue =>
-                      (ErrorMsg.error (SOME loc) "Bad type for final expression of source file.";
-                       preface ("Actual:", p_typ t);
-                       preface ("Needed:", p_typ tInit))
+               handle Unify _ =>
+                      if printActionDiffs {have = t, need = tInit} then
+                          ()
+                      else
+                          ErrorMsg.error (SOME loc) "File ends in something that isn't a directive."                      
            end;
        G'
     end
            end;
        G'
     end