module LoadModule (load) where import AbsDep import LexDep import ParDep import ErrM import Util import Control.Monad (liftM) import Data.List (union, partition, (\\)) import Data.Maybe (fromMaybe) findModule :: String -> IO FilePath findModule n = return (n ++ ".dep") readModule :: FilePath -> IO Module readModule f = do c <- readFile f case parseModule c of Ok m -> return m Bad e -> fail e parseModule :: String -> Err Module parseModule = pModule . tokens loadModule :: String -> IO Module loadModule n = findModule n >>= readModule -- load the given modules and their dependencies loadModules :: [String] -> IO [(String,Module)] loadModules [] = return [] loadModules (n:ns) = do m <- loadModule n ms <- loadModules (getDeps m `union` ns) return ((n,m):ms) getDeps :: Module -> [String] getDeps (Module is _) = [i | Import (Ident i) <- is] -- topologically sort modules by their dependencies sortDeps :: [(String,Module)] -> [(String,Module)] sortDeps ms = [ (n, lookup' n ms) | n <- sortDeps_ ms' ] where ms' = [ (n, getDeps m) | (n,m) <- ms ] sortDeps_ [] = [] sortDeps_ ds = ns ++ sortDeps_ [ (n, m \\ ns) | (n,m) <- rs ] where (es,rs) = partition (null . snd) ds ns = map fst es -- load modules and return them topologically sorted load :: [String] -> IO [(String,Module)] load = liftM sortDeps . loadModules