module Language.PureScript.ModuleDependencies (
sortModules,
ModuleGraph
) where
import Data.Data
import Data.Graph
import Data.Generics
import Data.List (nub)
import Language.PureScript.Declarations
import Language.PureScript.Names
type ModuleGraph = [(ModuleName, [ModuleName])]
sortModules :: [Module] -> Either String ([Module], ModuleGraph)
sortModules ms = do
let verts = map (\m -> (m, getModuleName m, usedModules m)) ms
ms' <- mapM toModule $ stronglyConnComp verts
let moduleGraph = map (\(_, mn, deps) -> (mn, deps)) verts
return (ms', moduleGraph)
usedModules :: (Data d) => d -> [ModuleName]
usedModules = nub . everything (++) (mkQ [] qualifiedIdents `extQ` qualifiedProperNames `extQ` imports)
where
qualifiedIdents :: Qualified Ident -> [ModuleName]
qualifiedIdents (Qualified (Just mn) _) = [mn]
qualifiedIdents _ = []
qualifiedProperNames :: Qualified ProperName -> [ModuleName]
qualifiedProperNames (Qualified (Just mn) _) = [mn]
qualifiedProperNames _ = []
imports :: Declaration -> [ModuleName]
imports (ImportDeclaration mn _ _) = [mn]
imports (PositionedDeclaration _ d) = imports d
imports _ = []
getModuleName :: Module -> ModuleName
getModuleName (Module mn _ _) = mn
toModule :: SCC Module -> Either String Module
toModule (AcyclicSCC m) = return m
toModule (CyclicSCC [m]) = return m
toModule (CyclicSCC ms) = Left $ "Cycle in module dependencies: " ++ show (map getModuleName ms)