Move ambient environment defaults into Env.env
[hcoop/domtool2.git] / src / order.sml
index 422856d..117a0ea 100644 (file)
@@ -1,5 +1,6 @@
 (* HCoop Domtool (http://hcoop.sourceforge.net/)
  * Copyright (c) 2006, Adam Chlipala
+ * Copyright (c) 2014 Clinton Ebadi <clinton@unknownlamer.org>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -120,6 +121,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
@@ -131,6 +135,11 @@ fun declNeeded G (d, _, _) =
                                   NONE => expNeeded G e
                                 | SOME t => unionCTE ((typNeeded G t, SS.empty),
                                                       expNeeded G e))
+      | DEnv (name, to, e) => (Env.bindInitialDynEnvVal G (name, dt, (Ast.ESkip, ErrorMsg.dummyLoc)),
+                              case to of
+                                  NONE => expNeeded G e
+                                | SOME t => unionCTE ((typNeeded G t, SS.empty),
+                                                      expNeeded G e))
       | DContext name => (Env.bindContext G name, empty)
 
 fun fileSig (_, ds, eo) =
@@ -163,23 +172,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 +223,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 +260,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,23 +292,39 @@ 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
-       (*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, []))
+       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
 
+val order = fn basisOpt => fn 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
+                                 (providers, fnames)
+                             end
+
 type providers = {provideC : string SM.map,
                  provideT : string SM.map,
                  provideV : string SM.map}