Put files called lib.dtl first in dependency orderings
[hcoop/domtool2.git] / src / order.sml
index 422856d..14bd01e 100644 (file)
@@ -120,6 +120,9 @@ fun expNeeded G (e, loc) =
                   empty es
       | ELocal (e1, e2) => unionCTE (expNeeded G e1, expNeeded G e2)
       | EWith (e1, e2) => unionCTE (expNeeded G e1, expNeeded G e2)
+      | EIf (e1, e2, e3) => unionCTE (expNeeded G e1,
+                                     unionCTE (expNeeded G e2,
+                                               expNeeded G e3))
 
 fun declNeeded G (d, _, _) =
     case d of
@@ -163,23 +166,33 @@ fun printSig ((cs, ts), vs) =
      SS.app (fn s => (print " "; print s; print ";")) vs;
      print "\n")
 
+val allNaughty = ref false
+val naughtyFiles = ref SS.empty
+fun addNaughty fname = naughtyFiles := SS.add (!naughtyFiles, fname)
+
 fun mergeProvide kind fname (m1, m2) =
     SS.foldl (fn (name, provide) =>
                 (case SM.find (provide, name) of
                      NONE => ()
-                   | SOME fname' => ErrorMsg.error NONE (String.concat ["Files ",
-                                                                        fname',
-                                                                        " and ",
-                                                                        fname,
-                                                                        " both provide ",
-                                                                        kind,
-                                                                        " ",
-                                                                        name]);
+                   | SOME fname' =>
+                     (addNaughty fname;
+                      addNaughty fname';
+                      ErrorMsg.error NONE (String.concat ["Files ",
+                                                          fname',
+                                                          " and ",
+                                                          fname,
+                                                          " both provide ",
+                                                          kind,
+                                                          " ",
+                                                          name]));
                  SM.insert (provide, name, fname)))
     m1 m2
 
 fun order basisOpt fnames =
     let
+       val () = allNaughty := false
+       val () = naughtyFiles := SS.empty
+
        fun doFile (fname, (provideC, provideT, provideV, require)) =
            let
                val file = Parse.parse fname
@@ -204,7 +217,8 @@ fun order basisOpt fnames =
                                                           if lastChance name then
                                                               need
                                                           else
-                                                              (ErrorMsg.error NONE
+                                                              (addNaughty fname;
+                                                               ErrorMsg.error NONE
                                                                               ("File "
                                                                                ^ fname
                                                                                ^ " uses undefined "
@@ -240,7 +254,8 @@ fun order basisOpt fnames =
                if SM.numItems waiting = 0 then
                    rev order
                else
-                   (ErrorMsg.error NONE "Cyclic dependency in source files";
+                   (allNaughty := true;
+                    ErrorMsg.error NONE "Cyclic dependency in source files";
                     order)
              | SOME next =>
                let
@@ -271,21 +286,37 @@ fun order basisOpt fnames =
                              (ready,
                               SM.insert (waiting, fname, requires)))
                      (SS.empty, SM.empty) require
+
+       val ordered = loop (ready, waiting, [])
+       val provider = {provideC = provideC,
+                       provideT = provideT,
+                       provideV = provideV}
+    in
+       if !allNaughty then
+           (provider, [])
+       else if SS.isEmpty (!naughtyFiles) then
+           (provider, ordered)
+       else
+           order basisOpt (List.filter (fn fname => not (SS.member (!naughtyFiles, fname))) fnames)
+    end
+
+fun order basisOpt fnames =
+    let
+       val (providers, fnames) = order basisOpt fnames
+
+       val (hasLib, fnames) = foldl (fn (fname, (hasLib, fnames)) =>
+                                        if OS.Path.file fname = "lib.dtl" then
+                                            (SOME fname, fnames)
+                                        else
+                                            (hasLib, fname :: fnames))
+                              (NONE, []) fnames
+
+       val fnames = rev fnames
+       val fnames = case hasLib of
+                        NONE => fnames
+                      | SOME hasLib => hasLib :: fnames
     in
-       (*SM.appi (fn (name, fname) => print ("Context " ^ name ^ " in " ^ fname ^ "\n")) provideC;
-       SM.appi (fn (name, fname) => print ("Type " ^ name ^ " in " ^ fname ^ "\n")) provideT;
-       SM.appi (fn (name, fname) => print ("Value " ^ name ^ " in " ^ fname ^ "\n")) provideV;*)
-
-       (*SM.appi (fn (fname, requires) =>
-                   (print fname;
-                    print " requires:";
-                    SS.app (fn fname' => (print " "; print fname')) requires;
-                    print "\n")) require;*)
-
-       ({provideC = provideC,
-         provideT = provideT,
-         provideV = provideV},
-        loop (ready, waiting, []))
+       (providers, fnames)
     end
 
 type providers = {provideC : string SM.map,