{- -----------------------------------------------------------------------------
Copyright 2020 Kevin P. Barry

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
----------------------------------------------------------------------------- -}

-- Author: Kevin P. Barry [ta0kira@gmail.com]

module Module.ProcessMetadata (
  MetadataMap,
  createCachePath,
  eraseCachedData,
  findSourceFiles,
  getCachedPath,
  getCacheRelativePath,
  getExprMap,
  getIncludePathsForDeps,
  getLinkFlagsForDeps,
  getNamespacesForDeps,
  getObjectFilesForDeps,
  getObjectFileResolver,
  getRealPathsForDeps,
  getSourceFilesForDeps,
  isPathConfigured,
  isPathUpToDate,
  loadModuleGlobals,
  loadModuleMetadata,
  loadPrivateDeps,
  loadPublicDeps,
  loadRecompile,
  loadTestingDeps,
  mapMetadata,
  resolveCategoryDeps,
  resolveObjectDeps,
  sortCompiledFiles,
  writeCachedFile,
  writeMetadata,
  writeRecompile,
) where

import Control.Applicative ((<|>))
import Control.Monad (when)
import Data.List (isSuffixOf)
import Data.Maybe (isJust)
import System.Directory
import System.FilePath
import System.IO
import Text.Parsec (SourcePos)
import qualified Data.Map as Map
import qualified Data.Set as Set

import Base.CompileError
import Base.CompileInfo
import Cli.CompileOptions
import Cli.Programs (VersionHash(..))
import Compilation.ProcedureContext (ExprMap)
import CompilerCxx.Category (CxxOutput(..))
import Module.CompileMetadata
import Module.ParseMetadata -- Not safe, due to Text.Regex.TDFA.
import Module.Paths
import Parser.SourceFile
import Types.Pragma
import Types.Procedure (Expression(Literal),ValueLiteral(..))
import Types.TypeCategory
import Types.TypeInstance


cachedDataPath :: FilePath
cachedDataPath :: FilePath
cachedDataPath = FilePath
".zeolite-cache"

moduleFilename :: FilePath
moduleFilename :: FilePath
moduleFilename = FilePath
".zeolite-module"

metadataFilename :: FilePath
metadataFilename :: FilePath
metadataFilename = FilePath
"compile-metadata"

type MetadataMap = Map.Map FilePath CompileMetadata

mapMetadata :: [CompileMetadata] -> MetadataMap
mapMetadata :: [CompileMetadata] -> MetadataMap
mapMetadata [CompileMetadata]
cs = [(FilePath, CompileMetadata)] -> MetadataMap
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(FilePath, CompileMetadata)] -> MetadataMap)
-> [(FilePath, CompileMetadata)] -> MetadataMap
forall a b. (a -> b) -> a -> b
$ [FilePath] -> [CompileMetadata] -> [(FilePath, CompileMetadata)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((CompileMetadata -> FilePath) -> [CompileMetadata] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> FilePath
cmPath [CompileMetadata]
cs) [CompileMetadata]
cs

loadRecompile :: FilePath -> CompileInfoIO ModuleConfig
loadRecompile :: FilePath -> CompileInfoIO ModuleConfig
loadRecompile FilePath
p = do
  let f :: FilePath
f = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename
  Bool
isFile <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
p
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is not a directory"
  Bool
isDir <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
p
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" does not exist"
  Bool
filePresent <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
filePresent) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" has not been configured yet"
  FilePath
c <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
readFile FilePath
f
  (FilePath -> FilePath -> CompileInfoIO ModuleConfig
forall a (m :: * -> *).
(ConfigFormat a, CompileErrorM m) =>
FilePath -> FilePath -> m a
autoReadConfig FilePath
f FilePath
c) CompileInfoIO ModuleConfig
-> FilePath -> CompileInfoIO ModuleConfig
forall (m :: * -> *) a. CompileErrorM m => m a -> FilePath -> m a
<!!
    (FilePath
"Could not parse metadata from \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"; please reconfigure")

isPathUpToDate :: VersionHash -> ForceMode -> FilePath -> CompileInfoIO Bool
isPathUpToDate :: VersionHash -> ForceMode -> FilePath -> CompileInfoT IO Bool
isPathUpToDate VersionHash
h ForceMode
f FilePath
p = do
  CompileInfo [CompileMetadata]
m <- IO (CompileInfo [CompileMetadata])
-> CompileInfoT IO (CompileInfo [CompileMetadata])
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO (CompileInfo [CompileMetadata])
 -> CompileInfoT IO (CompileInfo [CompileMetadata]))
-> IO (CompileInfo [CompileMetadata])
-> CompileInfoT IO (CompileInfo [CompileMetadata])
forall a b. (a -> b) -> a -> b
$ CompileInfoT IO [CompileMetadata]
-> IO (CompileInfo [CompileMetadata])
forall (m :: * -> *) a.
Monad m =>
CompileInfoT m a -> m (CompileInfo a)
toCompileInfo (CompileInfoT IO [CompileMetadata]
 -> IO (CompileInfo [CompileMetadata]))
-> CompileInfoT IO [CompileMetadata]
-> IO (CompileInfo [CompileMetadata])
forall a b. (a -> b) -> a -> b
$ ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
forall k a. Map k a
Map.empty Set FilePath
forall a. Set a
Set.empty (\CompileMetadata
m2 -> CompileMetadata -> [FilePath]
cmPublicDeps CompileMetadata
m2 [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ CompileMetadata -> [FilePath]
cmPrivateDeps CompileMetadata
m2) [FilePath
p]
  Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> CompileInfoT IO Bool) -> Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileInfo [CompileMetadata] -> Bool
forall a. CompileInfo a -> Bool
isCompileError CompileInfo [CompileMetadata]
m

isPathConfigured :: FilePath -> FilePath -> CompileInfoIO Bool
isPathConfigured :: FilePath -> FilePath -> CompileInfoT IO Bool
isPathConfigured FilePath
p FilePath
d = do
  CompileInfo ModuleConfig
m <- IO (CompileInfo ModuleConfig)
-> CompileInfoT IO (CompileInfo ModuleConfig)
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO (CompileInfo ModuleConfig)
 -> CompileInfoT IO (CompileInfo ModuleConfig))
-> IO (CompileInfo ModuleConfig)
-> CompileInfoT IO (CompileInfo ModuleConfig)
forall a b. (a -> b) -> a -> b
$ CompileInfoIO ModuleConfig -> IO (CompileInfo ModuleConfig)
forall (m :: * -> *) a.
Monad m =>
CompileInfoT m a -> m (CompileInfo a)
toCompileInfo (CompileInfoIO ModuleConfig -> IO (CompileInfo ModuleConfig))
-> CompileInfoIO ModuleConfig -> IO (CompileInfo ModuleConfig)
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoIO ModuleConfig
loadRecompile (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
d)
  Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> CompileInfoT IO Bool) -> Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileInfo ModuleConfig -> Bool
forall a. CompileInfo a -> Bool
isCompileError CompileInfo ModuleConfig
m

writeMetadata :: FilePath -> CompileMetadata -> CompileInfoIO ()
writeMetadata :: FilePath -> CompileMetadata -> CompileInfoT IO ()
writeMetadata FilePath
p CompileMetadata
m = do
  FilePath
p' <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> FilePath -> IO ()
hPutStrLn Handle
stderr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Writing metadata for \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p' FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"."
  FilePath
m' <- CompileMetadata -> CompileInfoT IO FilePath
forall a (m :: * -> *).
(ConfigFormat a, CompileErrorM m) =>
a -> m FilePath
autoWriteConfig CompileMetadata
m CompileInfoT IO FilePath -> FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. CompileErrorM m => m a -> FilePath -> m a
<?? (FilePath
"In data for " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p)
  FilePath -> FilePath -> FilePath -> FilePath -> CompileInfoT IO ()
writeCachedFile FilePath
p' FilePath
"" FilePath
metadataFilename FilePath
m'

writeRecompile :: FilePath -> ModuleConfig -> CompileInfoIO ()
writeRecompile :: FilePath -> ModuleConfig -> CompileInfoT IO ()
writeRecompile FilePath
p ModuleConfig
m = do
  FilePath
p' <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  let f :: FilePath
f = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename
  IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> FilePath -> IO ()
hPutStrLn Handle
stderr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Updating config for \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p' FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"."
  FilePath
m' <- ModuleConfig -> CompileInfoT IO FilePath
forall a (m :: * -> *).
(ConfigFormat a, CompileErrorM m) =>
a -> m FilePath
autoWriteConfig ModuleConfig
m CompileInfoT IO FilePath -> FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. CompileErrorM m => m a -> FilePath -> m a
<?? (FilePath
"In data for " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p)
  IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
writeFile FilePath
f FilePath
m'

eraseCachedData :: FilePath -> CompileInfoIO ()
eraseCachedData :: FilePath -> CompileInfoT IO ()
eraseCachedData FilePath
p = do
  let d :: FilePath
d  = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath
  Bool
dirExists <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
d
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
dirExists (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ()
removeDirectoryRecursive FilePath
d

createCachePath :: FilePath -> CompileInfoIO ()
createCachePath :: FilePath -> CompileInfoT IO ()
createCachePath FilePath
p = do
  let f :: FilePath
f = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath
  Bool
exists <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
f
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
exists) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
False FilePath
f

writeCachedFile :: FilePath -> String -> FilePath -> String -> CompileInfoIO ()
writeCachedFile :: FilePath -> FilePath -> FilePath -> FilePath -> CompileInfoT IO ()
writeCachedFile FilePath
p FilePath
ns FilePath
f FilePath
c = do
  FilePath -> CompileInfoT IO ()
createCachePath FilePath
p
  IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
False (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath FilePath -> FilePath -> FilePath
</> FilePath
ns
  IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
writeFile (FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p FilePath
ns FilePath
f) FilePath
c

getCachedPath :: FilePath -> String -> FilePath -> FilePath
getCachedPath :: FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p FilePath
ns FilePath
f = FilePath -> FilePath
fixPath (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath FilePath -> FilePath -> FilePath
</> FilePath
ns FilePath -> FilePath -> FilePath
</> FilePath
f

getCacheRelativePath :: FilePath -> FilePath
getCacheRelativePath :: FilePath -> FilePath
getCacheRelativePath FilePath
f = FilePath
".." FilePath -> FilePath -> FilePath
</> FilePath
f

findSourceFiles :: FilePath -> FilePath -> CompileInfoIO ([FilePath],[FilePath],[FilePath])
findSourceFiles :: FilePath
-> FilePath -> CompileInfoIO ([FilePath], [FilePath], [FilePath])
findSourceFiles FilePath
p0 FilePath
p = do
  let absolute :: FilePath
absolute = FilePath
p0 FilePath -> FilePath -> FilePath
</> FilePath
p
  Bool
isFile <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
absolute
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
absolute FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is not a directory"
  Bool
isDir <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
absolute
  Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
absolute FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" does not exist"
  [FilePath]
ds <- IO [FilePath] -> CompileInfoT IO [FilePath]
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO [FilePath] -> CompileInfoT IO [FilePath])
-> IO [FilePath] -> CompileInfoT IO [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO [FilePath]
getDirectoryContents FilePath
absolute IO [FilePath] -> ([FilePath] -> IO [FilePath]) -> IO [FilePath]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [FilePath] -> IO [FilePath]
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath] -> IO [FilePath])
-> ([FilePath] -> [FilePath]) -> [FilePath] -> IO [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
p FilePath -> FilePath -> FilePath
</>)
  let ps :: [FilePath]
ps = (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rp") [FilePath]
ds
  let xs :: [FilePath]
xs = (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rx") [FilePath]
ds
  let ts :: [FilePath]
ts = (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rt") [FilePath]
ds
  ([FilePath], [FilePath], [FilePath])
-> CompileInfoIO ([FilePath], [FilePath], [FilePath])
forall (m :: * -> *) a. Monad m => a -> m a
return ([FilePath]
ps,[FilePath]
xs,[FilePath]
ts)

getExprMap :: FilePath -> ModuleConfig -> CompileInfoIO (ExprMap SourcePos)
getExprMap :: FilePath -> ModuleConfig -> CompileInfoIO (ExprMap SourcePos)
getExprMap FilePath
p ModuleConfig
m = do
  FilePath
path <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath (FilePath
p FilePath -> FilePath -> FilePath
</> ModuleConfig -> FilePath
mcRoot ModuleConfig
m FilePath -> FilePath -> FilePath
</> ModuleConfig -> FilePath
mcPath ModuleConfig
m)
  let defaults :: [(FilePath, Expression c)]
defaults = [(FilePath
"MODULE_PATH",ValueLiteral c -> Expression c
forall c. ValueLiteral c -> Expression c
Literal ([c] -> FilePath -> ValueLiteral c
forall c. [c] -> FilePath -> ValueLiteral c
StringLiteral [] FilePath
path))]
  ExprMap SourcePos -> CompileInfoIO (ExprMap SourcePos)
forall (m :: * -> *) a. Monad m => a -> m a
return (ExprMap SourcePos -> CompileInfoIO (ExprMap SourcePos))
-> ExprMap SourcePos -> CompileInfoIO (ExprMap SourcePos)
forall a b. (a -> b) -> a -> b
$ [(FilePath, Expression SourcePos)] -> ExprMap SourcePos
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(FilePath, Expression SourcePos)] -> ExprMap SourcePos)
-> [(FilePath, Expression SourcePos)] -> ExprMap SourcePos
forall a b. (a -> b) -> a -> b
$ ModuleConfig -> [(FilePath, Expression SourcePos)]
mcExprMap ModuleConfig
m [(FilePath, Expression SourcePos)]
-> [(FilePath, Expression SourcePos)]
-> [(FilePath, Expression SourcePos)]
forall a. [a] -> [a] -> [a]
++ [(FilePath, Expression SourcePos)]
forall c. [(FilePath, Expression c)]
defaults

getRealPathsForDeps :: [CompileMetadata] -> [FilePath]
getRealPathsForDeps :: [CompileMetadata] -> [FilePath]
getRealPathsForDeps = (CompileMetadata -> FilePath) -> [CompileMetadata] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> FilePath
cmPath

getSourceFilesForDeps :: [CompileMetadata] -> [FilePath]
getSourceFilesForDeps :: [CompileMetadata] -> [FilePath]
getSourceFilesForDeps = [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath])
-> ([CompileMetadata] -> [[FilePath]])
-> [CompileMetadata]
-> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> [FilePath])
-> [CompileMetadata] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [FilePath]
extract where
  extract :: CompileMetadata -> [FilePath]
extract CompileMetadata
m = (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (CompileMetadata -> FilePath
cmPath CompileMetadata
m FilePath -> FilePath -> FilePath
</>) (CompileMetadata -> [FilePath]
cmPublicFiles CompileMetadata
m)

getNamespacesForDeps :: [CompileMetadata] -> [Namespace]
getNamespacesForDeps :: [CompileMetadata] -> [Namespace]
getNamespacesForDeps = (Namespace -> Bool) -> [Namespace] -> [Namespace]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (Namespace -> Bool) -> Namespace -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Namespace -> Bool
isNoNamespace) ([Namespace] -> [Namespace])
-> ([CompileMetadata] -> [Namespace])
-> [CompileMetadata]
-> [Namespace]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> Namespace) -> [CompileMetadata] -> [Namespace]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> Namespace
cmPublicNamespace

getIncludePathsForDeps :: [CompileMetadata] -> [FilePath]
getIncludePathsForDeps :: [CompileMetadata] -> [FilePath]
getIncludePathsForDeps = [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath])
-> ([CompileMetadata] -> [[FilePath]])
-> [CompileMetadata]
-> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> [FilePath])
-> [CompileMetadata] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [FilePath]
cmPublicSubdirs

getLinkFlagsForDeps :: [CompileMetadata] -> [String]
getLinkFlagsForDeps :: [CompileMetadata] -> [FilePath]
getLinkFlagsForDeps = [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath])
-> ([CompileMetadata] -> [[FilePath]])
-> [CompileMetadata]
-> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> [FilePath])
-> [CompileMetadata] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [FilePath]
cmLinkFlags

getObjectFilesForDeps :: [CompileMetadata] -> [ObjectFile]
getObjectFilesForDeps :: [CompileMetadata] -> [ObjectFile]
getObjectFilesForDeps = [[ObjectFile]] -> [ObjectFile]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ObjectFile]] -> [ObjectFile])
-> ([CompileMetadata] -> [[ObjectFile]])
-> [CompileMetadata]
-> [ObjectFile]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> [ObjectFile])
-> [CompileMetadata] -> [[ObjectFile]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [ObjectFile]
cmObjectFiles

loadModuleMetadata :: VersionHash -> ForceMode -> MetadataMap -> FilePath ->
  CompileInfoIO CompileMetadata
loadModuleMetadata :: VersionHash
-> ForceMode
-> MetadataMap
-> FilePath
-> CompileInfoIO CompileMetadata
loadModuleMetadata VersionHash
h ForceMode
f MetadataMap
ca = ([CompileMetadata] -> CompileMetadata)
-> CompileInfoT IO [CompileMetadata]
-> CompileInfoIO CompileMetadata
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [CompileMetadata] -> CompileMetadata
forall a. [a] -> a
head (CompileInfoT IO [CompileMetadata]
 -> CompileInfoIO CompileMetadata)
-> (FilePath -> CompileInfoT IO [CompileMetadata])
-> FilePath
-> CompileInfoIO CompileMetadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca Set FilePath
forall a. Set a
Set.empty ([FilePath] -> CompileMetadata -> [FilePath]
forall a b. a -> b -> a
const []) ([FilePath] -> CompileInfoT IO [CompileMetadata])
-> (FilePath -> [FilePath])
-> FilePath
-> CompileInfoT IO [CompileMetadata]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
:[])

loadPublicDeps :: VersionHash -> ForceMode -> MetadataMap -> [FilePath] ->
  CompileInfoIO [CompileMetadata]
loadPublicDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadPublicDeps VersionHash
h ForceMode
f MetadataMap
ca = ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca Set FilePath
forall a. Set a
Set.empty CompileMetadata -> [FilePath]
cmPublicDeps

loadTestingDeps :: VersionHash -> ForceMode -> MetadataMap -> CompileMetadata ->
  CompileInfoIO [CompileMetadata]
loadTestingDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> CompileMetadata
-> CompileInfoT IO [CompileMetadata]
loadTestingDeps VersionHash
h ForceMode
f MetadataMap
ca CompileMetadata
m = ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca ([FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList [CompileMetadata -> FilePath
cmPath CompileMetadata
m]) CompileMetadata -> [FilePath]
cmPublicDeps (CompileMetadata -> [FilePath]
cmPublicDeps CompileMetadata
m [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ CompileMetadata -> [FilePath]
cmPrivateDeps CompileMetadata
m)

loadPrivateDeps :: VersionHash -> ForceMode -> MetadataMap -> [CompileMetadata] ->
  CompileInfoIO [CompileMetadata]
loadPrivateDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> [CompileMetadata]
-> CompileInfoT IO [CompileMetadata]
loadPrivateDeps VersionHash
h ForceMode
f MetadataMap
ca [CompileMetadata]
ms = do
  [CompileMetadata]
new <- ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca Set FilePath
pa (\CompileMetadata
m -> CompileMetadata -> [FilePath]
cmPublicDeps CompileMetadata
m [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ CompileMetadata -> [FilePath]
cmPrivateDeps CompileMetadata
m) [FilePath]
paths
  [CompileMetadata] -> CompileInfoT IO [CompileMetadata]
forall (m :: * -> *) a. Monad m => a -> m a
return ([CompileMetadata] -> CompileInfoT IO [CompileMetadata])
-> [CompileMetadata] -> CompileInfoT IO [CompileMetadata]
forall a b. (a -> b) -> a -> b
$ [CompileMetadata]
ms [CompileMetadata] -> [CompileMetadata] -> [CompileMetadata]
forall a. [a] -> [a] -> [a]
++ [CompileMetadata]
new where
    paths :: [FilePath]
paths = [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata -> [FilePath])
-> [CompileMetadata] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (\CompileMetadata
m -> CompileMetadata -> [FilePath]
cmPublicDeps CompileMetadata
m [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ CompileMetadata -> [FilePath]
cmPrivateDeps CompileMetadata
m) [CompileMetadata]
ms
    pa :: Set FilePath
pa = [FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList ([FilePath] -> Set FilePath) -> [FilePath] -> Set FilePath
forall a b. (a -> b) -> a -> b
$ (CompileMetadata -> FilePath) -> [CompileMetadata] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> FilePath
cmPath [CompileMetadata]
ms

loadDepsCommon :: ForceMode -> VersionHash -> MetadataMap -> Set.Set FilePath ->
  (CompileMetadata -> [FilePath]) -> [FilePath] -> CompileInfoIO [CompileMetadata]
loadDepsCommon :: ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> CompileInfoT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca Set FilePath
pa0 CompileMetadata -> [FilePath]
getDeps [FilePath]
ps = do
  (Set FilePath
_,[(FilePath, CompileMetadata)]
processed) <- CompileInfoT IO [FilePath]
fixedPaths CompileInfoT IO [FilePath]
-> ([FilePath]
    -> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)]))
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
collect (Set FilePath
pa0,[])
  let cached :: MetadataMap
cached = MetadataMap -> MetadataMap -> MetadataMap
forall k a. Ord k => Map k a -> Map k a -> Map k a
Map.union MetadataMap
ca ([(FilePath, CompileMetadata)] -> MetadataMap
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(FilePath, CompileMetadata)]
processed)
  ((FilePath, CompileMetadata) -> CompileInfoIO CompileMetadata)
-> [(FilePath, CompileMetadata)]
-> CompileInfoT IO [CompileMetadata]
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m [b]
mapErrorsM (MetadataMap
-> (FilePath, CompileMetadata) -> CompileInfoIO CompileMetadata
forall (m :: * -> *).
MonadIO m =>
MetadataMap
-> (FilePath, CompileMetadata) -> CompileInfoT m CompileMetadata
check MetadataMap
cached) [(FilePath, CompileMetadata)]
processed where
    enforce :: Bool
enforce = ForceMode
f ForceMode -> ForceMode -> Bool
forall a. Eq a => a -> a -> Bool
/= ForceMode
ForceAll
    fixedPaths :: CompileInfoT IO [FilePath]
fixedPaths = (FilePath -> CompileInfoT IO FilePath)
-> [FilePath] -> CompileInfoT IO [FilePath]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> CompileInfoT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath) [FilePath]
ps
    collect :: (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
collect xa :: (Set FilePath, [(FilePath, CompileMetadata)])
xa@(Set FilePath
pa,[(FilePath, CompileMetadata)]
xs) (FilePath
p:[FilePath]
ps2)
      | FilePath
p FilePath -> Set FilePath -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set FilePath
pa = (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
collect (Set FilePath, [(FilePath, CompileMetadata)])
xa [FilePath]
ps2
      | Bool
otherwise = do
          let continue :: CompileMetadata
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m [FilePath]
ds = (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
collect (FilePath
p FilePath -> Set FilePath -> Set FilePath
forall a. Ord a => a -> Set a -> Set a
`Set.insert` Set FilePath
pa,[(FilePath, CompileMetadata)]
xs [(FilePath, CompileMetadata)]
-> [(FilePath, CompileMetadata)] -> [(FilePath, CompileMetadata)]
forall a. [a] -> [a] -> [a]
++ [(FilePath
p,CompileMetadata
m)]) ([FilePath]
ps2 [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
ds)
          case FilePath
p FilePath -> MetadataMap -> Maybe CompileMetadata
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` MetadataMap
ca of
               Just CompileMetadata
m2 -> CompileMetadata
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m2 []
               Maybe CompileMetadata
Nothing -> do
                 IO () -> CompileInfoT IO ()
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO () -> CompileInfoT IO ()) -> IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ Handle -> FilePath -> IO ()
hPutStrLn Handle
stderr (FilePath -> IO ()) -> FilePath -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Loading metadata for dependency \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"."
                 CompileMetadata
m2 <- MetadataMap -> FilePath -> CompileInfoIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
p
                 let ds :: [FilePath]
ds = CompileMetadata -> [FilePath]
getDeps CompileMetadata
m2
                 CompileMetadata
-> [FilePath]
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m2 [FilePath]
ds
    collect (Set FilePath, [(FilePath, CompileMetadata)])
xa [FilePath]
_ = (Set FilePath, [(FilePath, CompileMetadata)])
-> CompileInfoT IO (Set FilePath, [(FilePath, CompileMetadata)])
forall (m :: * -> *) a. Monad m => a -> m a
return (Set FilePath, [(FilePath, CompileMetadata)])
xa
    check :: MetadataMap
-> (FilePath, CompileMetadata) -> CompileInfoT m CompileMetadata
check MetadataMap
cm (FilePath
p,CompileMetadata
m)
      | FilePath
p FilePath -> MetadataMap -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` MetadataMap
ca = CompileMetadata -> CompileInfoT m CompileMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return CompileMetadata
m
      | Bool
otherwise = do
          FilePath
p' <- IO FilePath -> CompileInfoT m FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT m FilePath)
-> IO FilePath -> CompileInfoT m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
          Bool -> CompileInfoT m () -> CompileInfoT m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CompileMetadata -> FilePath
cmPath CompileMetadata
m FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
/= FilePath
p') (CompileInfoT m () -> CompileInfoT m ())
-> CompileInfoT m () -> CompileInfoT m ()
forall a b. (a -> b) -> a -> b
$
            FilePath -> CompileInfoT m ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT m ()) -> FilePath -> CompileInfoT m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" has an invalid cache path and must be recompiled"
          CompileInfo ()
fresh <- IO (CompileInfo ()) -> CompileInfoT m (CompileInfo ())
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO (CompileInfo ()) -> CompileInfoT m (CompileInfo ()))
-> IO (CompileInfo ()) -> CompileInfoT m (CompileInfo ())
forall a b. (a -> b) -> a -> b
$ CompileInfoT IO () -> IO (CompileInfo ())
forall (m :: * -> *) a.
Monad m =>
CompileInfoT m a -> m (CompileInfo a)
toCompileInfo (CompileInfoT IO () -> IO (CompileInfo ()))
-> CompileInfoT IO () -> IO (CompileInfo ())
forall a b. (a -> b) -> a -> b
$ VersionHash
-> MetadataMap -> FilePath -> CompileMetadata -> CompileInfoT IO ()
checkModuleFreshness VersionHash
h MetadataMap
cm FilePath
p CompileMetadata
m CompileInfoT IO () -> FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => m a -> FilePath -> m a
<!!
            (FilePath
"Module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is out of date and should be recompiled")
          if Bool
enforce
             then CompileInfo () -> CompileInfoT m ()
forall (m :: * -> *) a.
Monad m =>
CompileInfo a -> CompileInfoT m a
fromCompileInfo   CompileInfo ()
fresh
             else CompileInfo () -> CompileInfoT m ()
forall (m :: * -> *) a.
Monad m =>
CompileInfo a -> CompileInfoT m ()
asCompileWarnings CompileInfo ()
fresh
          CompileMetadata -> CompileInfoT m CompileMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return CompileMetadata
m

loadMetadata :: MetadataMap -> FilePath -> CompileInfoIO CompileMetadata
loadMetadata :: MetadataMap -> FilePath -> CompileInfoIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
p = do
  FilePath
path <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  case FilePath
path FilePath -> MetadataMap -> Maybe CompileMetadata
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` MetadataMap
ca of
       Just CompileMetadata
cm -> CompileMetadata -> CompileInfoIO CompileMetadata
forall (m :: * -> *) a. Monad m => a -> m a
return CompileMetadata
cm
       Maybe CompileMetadata
Nothing -> do
         let f :: FilePath
f = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath FilePath -> FilePath -> FilePath
</> FilePath
metadataFilename
         Bool
isFile <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
p
         Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is not a directory"
         Bool
isDir <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
p
         Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" does not exist"
         Bool
filePresent <- IO Bool -> CompileInfoT IO Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> CompileInfoT IO Bool)
-> IO Bool -> CompileInfoT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f
         Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
filePresent) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" has not been compiled yet"
         FilePath
c <- IO FilePath -> CompileInfoT IO FilePath
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO FilePath -> CompileInfoT IO FilePath)
-> IO FilePath -> CompileInfoT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
readFile FilePath
f
         (FilePath -> FilePath -> CompileInfoIO CompileMetadata
forall a (m :: * -> *).
(ConfigFormat a, CompileErrorM m) =>
FilePath -> FilePath -> m a
autoReadConfig FilePath
f FilePath
c) CompileInfoIO CompileMetadata
-> FilePath -> CompileInfoIO CompileMetadata
forall (m :: * -> *) a. CompileErrorM m => m a -> FilePath -> m a
<!!
            (FilePath
"Could not parse metadata from \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"; please recompile")

sortCompiledFiles :: [FilePath] -> ([FilePath],[FilePath],[FilePath])
sortCompiledFiles :: [FilePath] -> ([FilePath], [FilePath], [FilePath])
sortCompiledFiles = (([FilePath], [FilePath], [FilePath])
 -> FilePath -> ([FilePath], [FilePath], [FilePath]))
-> ([FilePath], [FilePath], [FilePath])
-> [FilePath]
-> ([FilePath], [FilePath], [FilePath])
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ([FilePath], [FilePath], [FilePath])
-> FilePath -> ([FilePath], [FilePath], [FilePath])
split ([],[],[]) where
  split :: ([FilePath], [FilePath], [FilePath])
-> FilePath -> ([FilePath], [FilePath], [FilePath])
split fs :: ([FilePath], [FilePath], [FilePath])
fs@([FilePath]
hxx,[FilePath]
cxx,[FilePath]
os) FilePath
f
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".hpp" FilePath
f = ([FilePath]
hxx[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f],[FilePath]
cxx,[FilePath]
os)
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".h"   FilePath
f = ([FilePath]
hxx[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f],[FilePath]
cxx,[FilePath]
os)
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".cpp" FilePath
f = ([FilePath]
hxx,[FilePath]
cxx[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f],[FilePath]
os)
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".cc"  FilePath
f = ([FilePath]
hxx,[FilePath]
cxx[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f],[FilePath]
os)
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".a"   FilePath
f = ([FilePath]
hxx,[FilePath]
cxx,[FilePath]
os[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f])
    | FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".o"   FilePath
f = ([FilePath]
hxx,[FilePath]
cxx,[FilePath]
os[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath
f])
    | Bool
otherwise = ([FilePath], [FilePath], [FilePath])
fs

checkModuleVersionHash :: VersionHash -> CompileMetadata -> Bool
checkModuleVersionHash :: VersionHash -> CompileMetadata -> Bool
checkModuleVersionHash VersionHash
h CompileMetadata
m = CompileMetadata -> VersionHash
cmVersionHash CompileMetadata
m VersionHash -> VersionHash -> Bool
forall a. Eq a => a -> a -> Bool
== VersionHash
h

checkModuleFreshness :: VersionHash -> MetadataMap -> FilePath -> CompileMetadata -> CompileInfoIO ()
checkModuleFreshness :: VersionHash
-> MetadataMap -> FilePath -> CompileMetadata -> CompileInfoT IO ()
checkModuleFreshness VersionHash
h MetadataMap
ca FilePath
p m :: CompileMetadata
m@(CompileMetadata VersionHash
_ FilePath
p2 Namespace
_ Namespace
_ [FilePath]
is [FilePath]
is2 [CategoryName]
_ [CategoryName]
_ [FilePath]
_ [FilePath]
_ [FilePath]
ps [FilePath]
xs [FilePath]
ts [FilePath]
hxx [FilePath]
cxx [FilePath]
bs [FilePath]
_ [ObjectFile]
os) = do
  UTCTime
time <- IO UTCTime -> CompileInfoT IO UTCTime
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO UTCTime -> CompileInfoT IO UTCTime)
-> IO UTCTime -> CompileInfoT IO UTCTime
forall a b. (a -> b) -> a -> b
$ FilePath -> IO UTCTime
getModificationTime (FilePath -> IO UTCTime) -> FilePath -> IO UTCTime
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p FilePath
"" FilePath
metadataFilename
  ([FilePath]
ps2,[FilePath]
xs2,[FilePath]
ts2) <- FilePath
-> FilePath -> CompileInfoIO ([FilePath], [FilePath], [FilePath])
findSourceFiles FilePath
p FilePath
""
  let rs :: [CategoryIdentifier]
rs = Set CategoryIdentifier -> [CategoryIdentifier]
forall a. Set a -> [a]
Set.toList (Set CategoryIdentifier -> [CategoryIdentifier])
-> Set CategoryIdentifier -> [CategoryIdentifier]
forall a b. (a -> b) -> a -> b
$ [CategoryIdentifier] -> Set CategoryIdentifier
forall a. Ord a => [a] -> Set a
Set.fromList ([CategoryIdentifier] -> Set CategoryIdentifier)
-> [CategoryIdentifier] -> Set CategoryIdentifier
forall a b. (a -> b) -> a -> b
$ [[CategoryIdentifier]] -> [CategoryIdentifier]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[CategoryIdentifier]] -> [CategoryIdentifier])
-> [[CategoryIdentifier]] -> [CategoryIdentifier]
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> [CategoryIdentifier])
-> [ObjectFile] -> [[CategoryIdentifier]]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> [CategoryIdentifier]
getRequires [ObjectFile]
os
  [CompileInfoT IO ()] -> CompileInfoT IO ()
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, CompileErrorM m) =>
f (m a) -> m ()
collectAllM_ ([CompileInfoT IO ()] -> CompileInfoT IO ())
-> [CompileInfoT IO ()] -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ [
      CompileInfoT IO ()
checkHash,
      UTCTime -> FilePath -> CompileInfoT IO ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename),
      [FilePath] -> [FilePath] -> CompileInfoT IO ()
forall (m :: * -> *).
CompileErrorM m =>
[FilePath] -> [FilePath] -> m ()
checkMissing [FilePath]
ps [FilePath]
ps2,
      [FilePath] -> [FilePath] -> CompileInfoT IO ()
forall (m :: * -> *).
CompileErrorM m =>
[FilePath] -> [FilePath] -> m ()
checkMissing [FilePath]
xs [FilePath]
xs2,
      [FilePath] -> [FilePath] -> CompileInfoT IO ()
forall (m :: * -> *).
CompileErrorM m =>
[FilePath] -> [FilePath] -> m ()
checkMissing [FilePath]
ts [FilePath]
ts2
    ] [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> CompileInfoT IO ())
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> CompileInfoT IO ()
checkDep UTCTime
time) ([FilePath] -> [CompileInfoT IO ()])
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> a -> b
$ [FilePath]
is [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
is2) [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> CompileInfoT IO ())
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> CompileInfoT IO ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath -> CompileInfoT IO ())
-> (FilePath -> FilePath) -> FilePath -> CompileInfoT IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
p2 FilePath -> FilePath -> FilePath
</>)) ([FilePath] -> [CompileInfoT IO ()])
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> a -> b
$ [FilePath]
ps [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
xs) [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> CompileInfoT IO ())
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> CompileInfoT IO ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath -> CompileInfoT IO ())
-> (FilePath -> FilePath) -> FilePath -> CompileInfoT IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p2 FilePath
"") ([FilePath] -> [CompileInfoT IO ()])
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> a -> b
$ [FilePath]
hxx [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
cxx) [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> CompileInfoT IO ())
-> [FilePath] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> CompileInfoT IO ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
FilePath -> m ()
checkOutput [FilePath]
bs) [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((ObjectFile -> CompileInfoT IO ())
-> [ObjectFile] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> CompileInfoT IO ()
forall (m :: * -> *).
(CompileErrorM m, MonadIO m) =>
ObjectFile -> m ()
checkObject [ObjectFile]
os) [CompileInfoT IO ()]
-> [CompileInfoT IO ()] -> [CompileInfoT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((CategoryIdentifier -> CompileInfoT IO ())
-> [CategoryIdentifier] -> [CompileInfoT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map CategoryIdentifier -> CompileInfoT IO ()
checkRequire [CategoryIdentifier]
rs)
  where
    checkHash :: CompileInfoT IO ()
checkHash =
      Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ VersionHash -> CompileMetadata -> Bool
checkModuleVersionHash VersionHash
h CompileMetadata
m) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$
        FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" was compiled with a different compiler setup"
    checkInput :: UTCTime -> FilePath -> m ()
checkInput UTCTime
time FilePath
f = do
      Bool
exists <- FilePath -> m Bool
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
FilePath -> m Bool
doesFileOrDirExist FilePath
f
      Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
exists) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Required path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is missing"
      UTCTime
time2 <- IO UTCTime -> m UTCTime
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO UTCTime -> m UTCTime) -> IO UTCTime -> m UTCTime
forall a b. (a -> b) -> a -> b
$ FilePath -> IO UTCTime
getModificationTime FilePath
f
      Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (UTCTime
time2 UTCTime -> UTCTime -> Bool
forall a. Ord a => a -> a -> Bool
> UTCTime
time) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Required path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is newer than cached data"
    checkOutput :: FilePath -> m ()
checkOutput FilePath
f = do
      Bool
exists <- IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f
      Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
exists) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> m ()) -> FilePath -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Output file \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is missing"
    checkDep :: UTCTime -> FilePath -> CompileInfoT IO ()
checkDep UTCTime
time FilePath
dep = do
      CompileMetadata
cm <- MetadataMap -> FilePath -> CompileInfoIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
dep
      (FilePath -> CompileInfoT IO ())
-> [FilePath] -> CompileInfoT IO ()
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m ()
mapErrorsM_ (UTCTime -> FilePath -> CompileInfoT IO ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath -> CompileInfoT IO ())
-> (FilePath -> FilePath) -> FilePath -> CompileInfoT IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> FilePath
cmPath CompileMetadata
cm FilePath -> FilePath -> FilePath
</>)) ([FilePath] -> CompileInfoT IO ())
-> [FilePath] -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> [FilePath]
cmPublicFiles CompileMetadata
cm
    checkObject :: ObjectFile -> m ()
checkObject (CategoryObjectFile CategoryIdentifier
_ [CategoryIdentifier]
_ [FilePath]
fs) = (FilePath -> m ()) -> [FilePath] -> m ()
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m ()
mapErrorsM_ FilePath -> m ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
FilePath -> m ()
checkOutput [FilePath]
fs
    checkObject (OtherObjectFile FilePath
f)         = FilePath -> m ()
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
FilePath -> m ()
checkOutput FilePath
f
    getRequires :: ObjectFile -> [CategoryIdentifier]
getRequires (CategoryObjectFile CategoryIdentifier
_ [CategoryIdentifier]
rs [FilePath]
_) = [CategoryIdentifier]
rs
    getRequires ObjectFile
_                           = []
    checkRequire :: CategoryIdentifier -> CompileInfoT IO ()
checkRequire (CategoryIdentifier FilePath
d CategoryName
c Namespace
ns) = do
      CompileMetadata
cm <- MetadataMap -> FilePath -> CompileInfoIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
d
      Bool -> CompileInfoT IO () -> CompileInfoT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (CompileMetadata -> FilePath
cmPath CompileMetadata
cm FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
/= FilePath
p2 Bool -> Bool -> Bool
&& Namespace
ns Namespace -> Namespace -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMetadata -> Namespace
cmPublicNamespace CompileMetadata
cm) (CompileInfoT IO () -> CompileInfoT IO ())
-> CompileInfoT IO () -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$
        FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Required category " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ CategoryName -> FilePath
forall a. Show a => a -> FilePath
show CategoryName
c FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" is newer than cached data"
    checkRequire (UnresolvedCategory CategoryName
c) =
      FilePath -> CompileInfoT IO ()
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> CompileInfoT IO ()) -> FilePath -> CompileInfoT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Required category " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ CategoryName -> FilePath
forall a. Show a => a -> FilePath
show CategoryName
c FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" is unresolved"
    checkMissing :: [FilePath] -> [FilePath] -> m ()
checkMissing [FilePath]
s0 [FilePath]
s1 = do
      let missing :: [FilePath]
missing = Set FilePath -> [FilePath]
forall a. Set a -> [a]
Set.toList (Set FilePath -> [FilePath]) -> Set FilePath -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList [FilePath]
s1 Set FilePath -> Set FilePath -> Set FilePath
forall a. Ord a => Set a -> Set a -> Set a
`Set.difference` [FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList [FilePath]
s0
      (FilePath -> m Any) -> [FilePath] -> m ()
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m ()
mapErrorsM_ (\FilePath
f -> FilePath -> m Any
forall (m :: * -> *) a. CompileErrorM m => FilePath -> m a
compileErrorM (FilePath -> m Any) -> FilePath -> m Any
forall a b. (a -> b) -> a -> b
$ FilePath
"Required path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" has not been compiled") [FilePath]
missing
    doesFileOrDirExist :: FilePath -> m Bool
doesFileOrDirExist FilePath
f2 = do
      Bool
existF <- IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f2
      if Bool
existF
        then Bool -> m Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
        else IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, CompileErrorM m) => IO a -> m a
errorFromIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
f2

getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [FilePath]
getObjectFileResolver :: [ObjectFile] -> [Namespace] -> [CategoryName] -> [FilePath]
getObjectFileResolver [ObjectFile]
os [Namespace]
ns [CategoryName]
ds = [FilePath]
resolved [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
nonCategories where
  categories :: [ObjectFile]
categories    = (ObjectFile -> Bool) -> [ObjectFile] -> [ObjectFile]
forall a. (a -> Bool) -> [a] -> [a]
filter ObjectFile -> Bool
isCategoryObjectFile [ObjectFile]
os
  nonCategories :: [FilePath]
nonCategories = (ObjectFile -> FilePath) -> [ObjectFile] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> FilePath
oofFile ([ObjectFile] -> [FilePath]) -> [ObjectFile] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> Bool) -> [ObjectFile] -> [ObjectFile]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (ObjectFile -> Bool) -> ObjectFile -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ObjectFile -> Bool
isCategoryObjectFile) [ObjectFile]
os
  categoryMap :: Map (CategoryName, Namespace) ObjectFile
categoryMap = [((CategoryName, Namespace), ObjectFile)]
-> Map (CategoryName, Namespace) ObjectFile
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([((CategoryName, Namespace), ObjectFile)]
 -> Map (CategoryName, Namespace) ObjectFile)
-> [((CategoryName, Namespace), ObjectFile)]
-> Map (CategoryName, Namespace) ObjectFile
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> ((CategoryName, Namespace), ObjectFile))
-> [ObjectFile] -> [((CategoryName, Namespace), ObjectFile)]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> ((CategoryName, Namespace), ObjectFile)
keyByCategory2 [ObjectFile]
categories
  keyByCategory2 :: ObjectFile -> ((CategoryName, Namespace), ObjectFile)
keyByCategory2 ObjectFile
o = ((CategoryIdentifier -> CategoryName
ciCategory (CategoryIdentifier -> CategoryName)
-> CategoryIdentifier -> CategoryName
forall a b. (a -> b) -> a -> b
$ ObjectFile -> CategoryIdentifier
cofCategory ObjectFile
o,CategoryIdentifier -> Namespace
ciNamespace (CategoryIdentifier -> Namespace)
-> CategoryIdentifier -> Namespace
forall a b. (a -> b) -> a -> b
$ ObjectFile -> CategoryIdentifier
cofCategory ObjectFile
o),ObjectFile
o)
  objectMap :: Map CategoryIdentifier ObjectFile
objectMap = [(CategoryIdentifier, ObjectFile)]
-> Map CategoryIdentifier ObjectFile
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(CategoryIdentifier, ObjectFile)]
 -> Map CategoryIdentifier ObjectFile)
-> [(CategoryIdentifier, ObjectFile)]
-> Map CategoryIdentifier ObjectFile
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> (CategoryIdentifier, ObjectFile))
-> [ObjectFile] -> [(CategoryIdentifier, ObjectFile)]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> (CategoryIdentifier, ObjectFile)
keyBySpec [ObjectFile]
categories
  keyBySpec :: ObjectFile -> (CategoryIdentifier, ObjectFile)
keyBySpec ObjectFile
o = (ObjectFile -> CategoryIdentifier
cofCategory ObjectFile
o,ObjectFile
o)
  directDeps :: [ObjectFile]
directDeps = [[ObjectFile]] -> [ObjectFile]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ObjectFile]] -> [ObjectFile]) -> [[ObjectFile]] -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ (CategoryName -> [ObjectFile]) -> [CategoryName] -> [[ObjectFile]]
forall a b. (a -> b) -> [a] -> [b]
map CategoryName -> [ObjectFile]
resolveDep2 [CategoryName]
ds
  directResolved :: [CategoryIdentifier]
directResolved = (ObjectFile -> CategoryIdentifier)
-> [ObjectFile] -> [CategoryIdentifier]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> CategoryIdentifier
cofCategory [ObjectFile]
directDeps
  resolveDep2 :: CategoryName -> [ObjectFile]
resolveDep2 CategoryName
d = Maybe [ObjectFile] -> [ObjectFile]
forall a. Maybe [a] -> [a]
unwrap (Maybe [ObjectFile] -> [ObjectFile])
-> Maybe [ObjectFile] -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ (Maybe [ObjectFile] -> Maybe [ObjectFile] -> Maybe [ObjectFile])
-> Maybe [ObjectFile] -> [Maybe [ObjectFile]] -> Maybe [ObjectFile]
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Maybe [ObjectFile] -> Maybe [ObjectFile] -> Maybe [ObjectFile]
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) Maybe [ObjectFile]
forall a. Maybe a
Nothing [Maybe [ObjectFile]]
allChecks Maybe [ObjectFile] -> Maybe [ObjectFile] -> Maybe [ObjectFile]
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> [ObjectFile] -> Maybe [ObjectFile]
forall a. a -> Maybe a
Just [] where
    allChecks :: [Maybe [ObjectFile]]
allChecks = (Namespace -> Maybe [ObjectFile])
-> [Namespace] -> [Maybe [ObjectFile]]
forall a b. (a -> b) -> [a] -> [b]
map (\Namespace
n -> (CategoryName
d,Namespace
n) (CategoryName, Namespace)
-> Map (CategoryName, Namespace) ObjectFile -> Maybe ObjectFile
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map (CategoryName, Namespace) ObjectFile
categoryMap Maybe ObjectFile
-> (ObjectFile -> Maybe [ObjectFile]) -> Maybe [ObjectFile]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [ObjectFile] -> Maybe [ObjectFile]
forall (m :: * -> *) a. Monad m => a -> m a
return ([ObjectFile] -> Maybe [ObjectFile])
-> (ObjectFile -> [ObjectFile]) -> ObjectFile -> Maybe [ObjectFile]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ObjectFile -> [ObjectFile] -> [ObjectFile]
forall a. a -> [a] -> [a]
:[])) ([Namespace]
ns [Namespace] -> [Namespace] -> [Namespace]
forall a. [a] -> [a] -> [a]
++ [Namespace
NoNamespace])
    unwrap :: Maybe [a] -> [a]
unwrap (Just [a]
xs) = [a]
xs
    unwrap Maybe [a]
_         = []
  (Set CategoryIdentifier
_,Set FilePath
_,[FilePath]
resolved) = Set CategoryIdentifier
-> Set FilePath
-> [CategoryIdentifier]
-> (Set CategoryIdentifier, Set FilePath, [FilePath])
collectAll Set CategoryIdentifier
forall a. Set a
Set.empty Set FilePath
forall a. Set a
Set.empty [CategoryIdentifier]
directResolved
  collectAll :: Set CategoryIdentifier
-> Set FilePath
-> [CategoryIdentifier]
-> (Set CategoryIdentifier, Set FilePath, [FilePath])
collectAll Set CategoryIdentifier
ca Set FilePath
fa [] = (Set CategoryIdentifier
ca,Set FilePath
fa,[])
  collectAll Set CategoryIdentifier
ca Set FilePath
fa (CategoryIdentifier
c:[CategoryIdentifier]
cs)
    | CategoryIdentifier
c CategoryIdentifier -> Set CategoryIdentifier -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set CategoryIdentifier
ca = Set CategoryIdentifier
-> Set FilePath
-> [CategoryIdentifier]
-> (Set CategoryIdentifier, Set FilePath, [FilePath])
collectAll Set CategoryIdentifier
ca Set FilePath
fa [CategoryIdentifier]
cs
    | Bool
otherwise =
      case CategoryIdentifier
c CategoryIdentifier
-> Map CategoryIdentifier ObjectFile -> Maybe ObjectFile
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map CategoryIdentifier ObjectFile
objectMap of
           Just (CategoryObjectFile CategoryIdentifier
_ [CategoryIdentifier]
ds2 [FilePath]
fs) -> (Set CategoryIdentifier
ca',Set FilePath
fa'',[FilePath]
fs') where
             (Set CategoryIdentifier
ca',Set FilePath
fa',[FilePath]
fs0) = Set CategoryIdentifier
-> Set FilePath
-> [CategoryIdentifier]
-> (Set CategoryIdentifier, Set FilePath, [FilePath])
collectAll (CategoryIdentifier
c CategoryIdentifier
-> Set CategoryIdentifier -> Set CategoryIdentifier
forall a. Ord a => a -> Set a -> Set a
`Set.insert` Set CategoryIdentifier
ca) Set FilePath
fa ([CategoryIdentifier]
ds2 [CategoryIdentifier]
-> [CategoryIdentifier] -> [CategoryIdentifier]
forall a. [a] -> [a] -> [a]
++ [CategoryIdentifier]
cs)
             fa'' :: Set FilePath
fa'' = Set FilePath
fa' Set FilePath -> Set FilePath -> Set FilePath
forall a. Ord a => Set a -> Set a -> Set a
`Set.union` ([FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList [FilePath]
fs)
             fs' :: [FilePath]
fs' = ((FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (FilePath -> Bool) -> FilePath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> Set FilePath -> Bool)
-> Set FilePath -> FilePath -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip FilePath -> Set FilePath -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Set FilePath
fa') [FilePath]
fs) [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
fs0
           Maybe ObjectFile
_ -> Set CategoryIdentifier
-> Set FilePath
-> [CategoryIdentifier]
-> (Set CategoryIdentifier, Set FilePath, [FilePath])
collectAll Set CategoryIdentifier
ca Set FilePath
fa [CategoryIdentifier]
cs

resolveObjectDeps :: [CompileMetadata] -> FilePath -> FilePath -> [([FilePath],CxxOutput)] -> [ObjectFile]
resolveObjectDeps :: [CompileMetadata]
-> FilePath
-> FilePath
-> [([FilePath], CxxOutput)]
-> [ObjectFile]
resolveObjectDeps [CompileMetadata]
deps FilePath
p FilePath
d [([FilePath], CxxOutput)]
os = [ObjectFile]
resolvedCategories [ObjectFile] -> [ObjectFile] -> [ObjectFile]
forall a. [a] -> [a] -> [a]
++ [ObjectFile]
nonCategories where
  categories :: [([FilePath], CxxOutput)]
categories = (([FilePath], CxxOutput) -> Bool)
-> [([FilePath], CxxOutput)] -> [([FilePath], CxxOutput)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Maybe CategoryName -> Bool
forall a. Maybe a -> Bool
isJust (Maybe CategoryName -> Bool)
-> (([FilePath], CxxOutput) -> Maybe CategoryName)
-> ([FilePath], CxxOutput)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CxxOutput -> Maybe CategoryName
coCategory (CxxOutput -> Maybe CategoryName)
-> (([FilePath], CxxOutput) -> CxxOutput)
-> ([FilePath], CxxOutput)
-> Maybe CategoryName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath], CxxOutput) -> CxxOutput
forall a b. (a, b) -> b
snd) [([FilePath], CxxOutput)]
os
  publicNamespaces :: [Namespace]
publicNamespaces = [CompileMetadata] -> [Namespace]
getNamespacesForDeps [CompileMetadata]
deps
  nonCategories :: [ObjectFile]
nonCategories = (FilePath -> ObjectFile) -> [FilePath] -> [ObjectFile]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> ObjectFile
OtherObjectFile ([FilePath] -> [ObjectFile]) -> [FilePath] -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (([FilePath], CxxOutput) -> [FilePath])
-> [([FilePath], CxxOutput)] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map ([FilePath], CxxOutput) -> [FilePath]
forall a b. (a, b) -> a
fst ([([FilePath], CxxOutput)] -> [[FilePath]])
-> [([FilePath], CxxOutput)] -> [[FilePath]]
forall a b. (a -> b) -> a -> b
$ (([FilePath], CxxOutput) -> Bool)
-> [([FilePath], CxxOutput)] -> [([FilePath], CxxOutput)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (([FilePath], CxxOutput) -> Bool)
-> ([FilePath], CxxOutput)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe CategoryName -> Bool
forall a. Maybe a -> Bool
isJust (Maybe CategoryName -> Bool)
-> (([FilePath], CxxOutput) -> Maybe CategoryName)
-> ([FilePath], CxxOutput)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CxxOutput -> Maybe CategoryName
coCategory (CxxOutput -> Maybe CategoryName)
-> (([FilePath], CxxOutput) -> CxxOutput)
-> ([FilePath], CxxOutput)
-> Maybe CategoryName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath], CxxOutput) -> CxxOutput
forall a b. (a, b) -> b
snd) [([FilePath], CxxOutput)]
os
  resolvedCategories :: [ObjectFile]
resolvedCategories = Map CategoryIdentifier ObjectFile -> [ObjectFile]
forall k a. Map k a -> [a]
Map.elems (Map CategoryIdentifier ObjectFile -> [ObjectFile])
-> Map CategoryIdentifier ObjectFile -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> ObjectFile -> ObjectFile)
-> [(CategoryIdentifier, ObjectFile)]
-> Map CategoryIdentifier ObjectFile
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith ObjectFile -> ObjectFile -> ObjectFile
mergeObjectFiles ([(CategoryIdentifier, ObjectFile)]
 -> Map CategoryIdentifier ObjectFile)
-> [(CategoryIdentifier, ObjectFile)]
-> Map CategoryIdentifier ObjectFile
forall a b. (a -> b) -> a -> b
$ (([FilePath], CxxOutput) -> (CategoryIdentifier, ObjectFile))
-> [([FilePath], CxxOutput)] -> [(CategoryIdentifier, ObjectFile)]
forall a b. (a -> b) -> [a] -> [b]
map ([FilePath], CxxOutput) -> (CategoryIdentifier, ObjectFile)
resolveCategory [([FilePath], CxxOutput)]
categories
  categoryMap :: Map (CategoryName, Namespace) CategoryIdentifier
categoryMap = [((CategoryName, Namespace), CategoryIdentifier)]
-> Map (CategoryName, Namespace) CategoryIdentifier
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([((CategoryName, Namespace), CategoryIdentifier)]
 -> Map (CategoryName, Namespace) CategoryIdentifier)
-> [((CategoryName, Namespace), CategoryIdentifier)]
-> Map (CategoryName, Namespace) CategoryIdentifier
forall a b. (a -> b) -> a -> b
$ [((CategoryName, Namespace), CategoryIdentifier)]
directCategories [((CategoryName, Namespace), CategoryIdentifier)]
-> [((CategoryName, Namespace), CategoryIdentifier)]
-> [((CategoryName, Namespace), CategoryIdentifier)]
forall a. [a] -> [a] -> [a]
++ [((CategoryName, Namespace), CategoryIdentifier)]
depCategories
  directCategories :: [((CategoryName, Namespace), CategoryIdentifier)]
directCategories = (CxxOutput -> ((CategoryName, Namespace), CategoryIdentifier))
-> [CxxOutput] -> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> [a] -> [b]
map (CategoryIdentifier
-> ((CategoryName, Namespace), CategoryIdentifier)
keyByCategory (CategoryIdentifier
 -> ((CategoryName, Namespace), CategoryIdentifier))
-> (CxxOutput -> CategoryIdentifier)
-> CxxOutput
-> ((CategoryName, Namespace), CategoryIdentifier)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CxxOutput -> CategoryIdentifier
cxxToId) ([CxxOutput] -> [((CategoryName, Namespace), CategoryIdentifier)])
-> [CxxOutput] -> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> a -> b
$ (([FilePath], CxxOutput) -> CxxOutput)
-> [([FilePath], CxxOutput)] -> [CxxOutput]
forall a b. (a -> b) -> [a] -> [b]
map ([FilePath], CxxOutput) -> CxxOutput
forall a b. (a, b) -> b
snd [([FilePath], CxxOutput)]
categories
  depCategories :: [((CategoryName, Namespace), CategoryIdentifier)]
depCategories = (CategoryIdentifier
 -> ((CategoryName, Namespace), CategoryIdentifier))
-> [CategoryIdentifier]
-> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> [a] -> [b]
map CategoryIdentifier
-> ((CategoryName, Namespace), CategoryIdentifier)
keyByCategory ([CategoryIdentifier]
 -> [((CategoryName, Namespace), CategoryIdentifier)])
-> [CategoryIdentifier]
-> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> a -> b
$ [[CategoryIdentifier]] -> [CategoryIdentifier]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ((CompileMetadata -> [CategoryIdentifier])
-> [CompileMetadata] -> [[CategoryIdentifier]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [CategoryIdentifier]
categoriesToIds [CompileMetadata]
deps)
  getCats :: CompileMetadata -> [(CategoryName, Namespace)]
getCats CompileMetadata
dep = [CategoryName] -> [Namespace] -> [(CategoryName, Namespace)]
forall a b. [a] -> [b] -> [(a, b)]
zip (CompileMetadata -> [CategoryName]
cmPublicCategories CompileMetadata
dep) (Namespace -> [Namespace]
forall a. a -> [a]
repeat (Namespace -> [Namespace]) -> Namespace -> [Namespace]
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> Namespace
cmPublicNamespace CompileMetadata
dep) [(CategoryName, Namespace)]
-> [(CategoryName, Namespace)] -> [(CategoryName, Namespace)]
forall a. [a] -> [a] -> [a]
++
                -- Allow ModuleOnly when the path is the same. Only needed for tests.
                -- TODO: The path comparison here is sloppy.
                (if CompileMetadata -> FilePath
cmPath CompileMetadata
dep FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
p then [CategoryName] -> [Namespace] -> [(CategoryName, Namespace)]
forall a b. [a] -> [b] -> [(a, b)]
zip (CompileMetadata -> [CategoryName]
cmPrivateCategories CompileMetadata
dep) (Namespace -> [Namespace]
forall a. a -> [a]
repeat (Namespace -> [Namespace]) -> Namespace -> [Namespace]
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> Namespace
cmPrivateNamespace CompileMetadata
dep) else [])
  categoriesToIds :: CompileMetadata -> [CategoryIdentifier]
categoriesToIds CompileMetadata
dep = ((CategoryName, Namespace) -> CategoryIdentifier)
-> [(CategoryName, Namespace)] -> [CategoryIdentifier]
forall a b. (a -> b) -> [a] -> [b]
map ((CategoryName -> Namespace -> CategoryIdentifier)
-> (CategoryName, Namespace) -> CategoryIdentifier
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((CategoryName -> Namespace -> CategoryIdentifier)
 -> (CategoryName, Namespace) -> CategoryIdentifier)
-> (CategoryName -> Namespace -> CategoryIdentifier)
-> (CategoryName, Namespace)
-> CategoryIdentifier
forall a b. (a -> b) -> a -> b
$ FilePath -> CategoryName -> Namespace -> CategoryIdentifier
CategoryIdentifier (FilePath -> CategoryName -> Namespace -> CategoryIdentifier)
-> FilePath -> CategoryName -> Namespace -> CategoryIdentifier
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> FilePath
cmPath CompileMetadata
dep) ([(CategoryName, Namespace)] -> [CategoryIdentifier])
-> [(CategoryName, Namespace)] -> [CategoryIdentifier]
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> [(CategoryName, Namespace)]
getCats CompileMetadata
dep
  cxxToId :: CxxOutput -> CategoryIdentifier
cxxToId (CxxOutput (Just CategoryName
c) FilePath
_ Namespace
ns [Namespace]
_ [CategoryName]
_ [FilePath]
_) = FilePath -> CategoryName -> Namespace -> CategoryIdentifier
CategoryIdentifier FilePath
d CategoryName
c Namespace
ns
  cxxToId CxxOutput
_                               = CategoryIdentifier
forall a. HasCallStack => a
undefined
  resolveCategory :: ([FilePath], CxxOutput) -> (CategoryIdentifier, ObjectFile)
resolveCategory ([FilePath]
fs,ca :: CxxOutput
ca@(CxxOutput Maybe CategoryName
_ FilePath
_ Namespace
_ [Namespace]
ns2 [CategoryName]
ds [FilePath]
_)) =
    (CxxOutput -> CategoryIdentifier
cxxToId CxxOutput
ca,CategoryIdentifier
-> [CategoryIdentifier] -> [FilePath] -> ObjectFile
CategoryObjectFile (CxxOutput -> CategoryIdentifier
cxxToId CxxOutput
ca) ((CategoryIdentifier -> Bool)
-> [CategoryIdentifier] -> [CategoryIdentifier]
forall a. (a -> Bool) -> [a] -> [a]
filter (CategoryIdentifier -> CategoryIdentifier -> Bool
forall a. Eq a => a -> a -> Bool
/= CxxOutput -> CategoryIdentifier
cxxToId CxxOutput
ca) [CategoryIdentifier]
rs) [FilePath]
fs) where
      rs :: [CategoryIdentifier]
rs = [[CategoryIdentifier]] -> [CategoryIdentifier]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[CategoryIdentifier]] -> [CategoryIdentifier])
-> [[CategoryIdentifier]] -> [CategoryIdentifier]
forall a b. (a -> b) -> a -> b
$ (CategoryName -> [CategoryIdentifier])
-> [CategoryName] -> [[CategoryIdentifier]]
forall a b. (a -> b) -> [a] -> [b]
map (Map (CategoryName, Namespace) CategoryIdentifier
-> [Namespace] -> CategoryName -> [CategoryIdentifier]
resolveDep Map (CategoryName, Namespace) CategoryIdentifier
categoryMap ([Namespace]
ns2 [Namespace] -> [Namespace] -> [Namespace]
forall a. [a] -> [a] -> [a]
++ [Namespace]
publicNamespaces)) [CategoryName]
ds

resolveCategoryDeps :: [CategoryName] -> [CompileMetadata] -> [CategoryIdentifier]
resolveCategoryDeps :: [CategoryName] -> [CompileMetadata] -> [CategoryIdentifier]
resolveCategoryDeps [CategoryName]
cs [CompileMetadata]
deps = [CategoryIdentifier]
resolvedCategories where
  publicNamespaces :: [Namespace]
publicNamespaces = [CompileMetadata] -> [Namespace]
getNamespacesForDeps [CompileMetadata]
deps
  resolvedCategories :: [CategoryIdentifier]
resolvedCategories = [[CategoryIdentifier]] -> [CategoryIdentifier]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[CategoryIdentifier]] -> [CategoryIdentifier])
-> [[CategoryIdentifier]] -> [CategoryIdentifier]
forall a b. (a -> b) -> a -> b
$ (CategoryName -> [CategoryIdentifier])
-> [CategoryName] -> [[CategoryIdentifier]]
forall a b. (a -> b) -> [a] -> [b]
map (Map (CategoryName, Namespace) CategoryIdentifier
-> [Namespace] -> CategoryName -> [CategoryIdentifier]
resolveDep Map (CategoryName, Namespace) CategoryIdentifier
categoryMap [Namespace]
publicNamespaces) [CategoryName]
cs
  categoryMap :: Map (CategoryName, Namespace) CategoryIdentifier
categoryMap = [((CategoryName, Namespace), CategoryIdentifier)]
-> Map (CategoryName, Namespace) CategoryIdentifier
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [((CategoryName, Namespace), CategoryIdentifier)]
depCategories
  depCategories :: [((CategoryName, Namespace), CategoryIdentifier)]
depCategories = (ObjectFile -> ((CategoryName, Namespace), CategoryIdentifier))
-> [ObjectFile]
-> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> [a] -> [b]
map (CategoryIdentifier
-> ((CategoryName, Namespace), CategoryIdentifier)
keyByCategory (CategoryIdentifier
 -> ((CategoryName, Namespace), CategoryIdentifier))
-> (ObjectFile -> CategoryIdentifier)
-> ObjectFile
-> ((CategoryName, Namespace), CategoryIdentifier)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ObjectFile -> CategoryIdentifier
cofCategory) ([ObjectFile] -> [((CategoryName, Namespace), CategoryIdentifier)])
-> [ObjectFile]
-> [((CategoryName, Namespace), CategoryIdentifier)]
forall a b. (a -> b) -> a -> b
$ (ObjectFile -> Bool) -> [ObjectFile] -> [ObjectFile]
forall a. (a -> Bool) -> [a] -> [a]
filter ObjectFile -> Bool
isCategoryObjectFile ([ObjectFile] -> [ObjectFile]) -> [ObjectFile] -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ [[ObjectFile]] -> [ObjectFile]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[ObjectFile]] -> [ObjectFile]) -> [[ObjectFile]] -> [ObjectFile]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata -> [ObjectFile])
-> [CompileMetadata] -> [[ObjectFile]]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> [ObjectFile]
cmObjectFiles [CompileMetadata]
deps

keyByCategory :: CategoryIdentifier -> ((CategoryName,Namespace),CategoryIdentifier)
keyByCategory :: CategoryIdentifier
-> ((CategoryName, Namespace), CategoryIdentifier)
keyByCategory CategoryIdentifier
c = ((CategoryIdentifier -> CategoryName
ciCategory CategoryIdentifier
c,CategoryIdentifier -> Namespace
ciNamespace CategoryIdentifier
c),CategoryIdentifier
c)

resolveDep :: Map.Map (CategoryName,Namespace) CategoryIdentifier ->
  [Namespace] -> CategoryName -> [CategoryIdentifier]
resolveDep :: Map (CategoryName, Namespace) CategoryIdentifier
-> [Namespace] -> CategoryName -> [CategoryIdentifier]
resolveDep Map (CategoryName, Namespace) CategoryIdentifier
cm (Namespace
n:[Namespace]
ns) CategoryName
d =
  case (CategoryName
d,Namespace
n) (CategoryName, Namespace)
-> Map (CategoryName, Namespace) CategoryIdentifier
-> Maybe CategoryIdentifier
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map (CategoryName, Namespace) CategoryIdentifier
cm of
       Just CategoryIdentifier
xs -> [CategoryIdentifier
xs]
       Maybe CategoryIdentifier
Nothing -> Map (CategoryName, Namespace) CategoryIdentifier
-> [Namespace] -> CategoryName -> [CategoryIdentifier]
resolveDep Map (CategoryName, Namespace) CategoryIdentifier
cm [Namespace]
ns CategoryName
d
resolveDep Map (CategoryName, Namespace) CategoryIdentifier
_ [Namespace]
_ CategoryName
d = [CategoryName -> CategoryIdentifier
UnresolvedCategory CategoryName
d]

loadModuleGlobals :: PathIOHandler r => r -> FilePath -> (Namespace,Namespace) -> [FilePath] ->
  Maybe CompileMetadata -> [CompileMetadata] -> [CompileMetadata] ->
  CompileInfoIO ([WithVisibility (AnyCategory SourcePos)])
loadModuleGlobals :: r
-> FilePath
-> (Namespace, Namespace)
-> [FilePath]
-> Maybe CompileMetadata
-> [CompileMetadata]
-> [CompileMetadata]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
loadModuleGlobals r
r FilePath
p (Namespace
ns0,Namespace
ns1) [FilePath]
fs Maybe CompileMetadata
m [CompileMetadata]
deps1 [CompileMetadata]
deps2 = do
  let public :: Set FilePath
public = [FilePath] -> Set FilePath
forall a. Ord a => [a] -> Set a
Set.fromList ([FilePath] -> Set FilePath) -> [FilePath] -> Set FilePath
forall a b. (a -> b) -> a -> b
$ (CompileMetadata -> FilePath) -> [CompileMetadata] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> FilePath
cmPath [CompileMetadata]
deps1
  let deps2' :: [CompileMetadata]
deps2' = (CompileMetadata -> Bool) -> [CompileMetadata] -> [CompileMetadata]
forall a. (a -> Bool) -> [a] -> [a]
filter (\CompileMetadata
cm -> Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> FilePath
cmPath CompileMetadata
cm FilePath -> Set FilePath -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` Set FilePath
public) [CompileMetadata]
deps2
  [WithVisibility (AnyCategory SourcePos)]
cs0 <- ([[WithVisibility (AnyCategory SourcePos)]]
 -> [WithVisibility (AnyCategory SourcePos)])
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[WithVisibility (AnyCategory SourcePos)]]
-> [WithVisibility (AnyCategory SourcePos)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
 -> CompileInfoIO [WithVisibility (AnyCategory SourcePos)])
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata
 -> CompileInfoIO [WithVisibility (AnyCategory SourcePos)])
-> [CompileMetadata]
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m [b]
mapErrorsM (Bool
-> [CodeVisibility]
-> CompileMetadata
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourcePos)]
processDeps Bool
False [CodeVisibility
FromDependency])            [CompileMetadata]
deps1
  [WithVisibility (AnyCategory SourcePos)]
cs1 <- ([[WithVisibility (AnyCategory SourcePos)]]
 -> [WithVisibility (AnyCategory SourcePos)])
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[WithVisibility (AnyCategory SourcePos)]]
-> [WithVisibility (AnyCategory SourcePos)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
 -> CompileInfoIO [WithVisibility (AnyCategory SourcePos)])
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata
 -> CompileInfoIO [WithVisibility (AnyCategory SourcePos)])
-> [CompileMetadata]
-> CompileInfoT IO [[WithVisibility (AnyCategory SourcePos)]]
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m [b]
mapErrorsM (Bool
-> [CodeVisibility]
-> CompileMetadata
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourcePos)]
processDeps Bool
False [CodeVisibility
FromDependency,CodeVisibility
ModuleOnly]) [CompileMetadata]
deps2'
  [WithVisibility (AnyCategory SourcePos)]
cs2 <- (Namespace, Namespace)
-> [FilePath]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
(Namespace, Namespace)
-> [FilePath] -> m [WithVisibility (AnyCategory SourcePos)]
loadAllPublic (Namespace
ns0,Namespace
ns1) [FilePath]
fs
  [WithVisibility (AnyCategory SourcePos)]
cs3 <- case Maybe CompileMetadata
m of
              Just CompileMetadata
m2 -> Bool
-> [CodeVisibility]
-> CompileMetadata
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourcePos)]
processDeps Bool
True [CodeVisibility
FromDependency] CompileMetadata
m2
              Maybe CompileMetadata
_       -> [WithVisibility (AnyCategory SourcePos)]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *) a. Monad m => a -> m a
return []
  [WithVisibility (AnyCategory SourcePos)]
-> CompileInfoIO [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([WithVisibility (AnyCategory SourcePos)]
cs0[WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourcePos)]
cs1[WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourcePos)]
cs2[WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourcePos)]
cs3) where
    processDeps :: Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourcePos)]
processDeps Bool
same [CodeVisibility]
ss CompileMetadata
dep = do
      let fs2 :: [FilePath]
fs2 = [CompileMetadata] -> [FilePath]
getSourceFilesForDeps [CompileMetadata
dep]
      [WithVisibility (AnyCategory SourcePos)]
cs <- (Namespace, Namespace)
-> [FilePath] -> m [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
(MonadIO m, CompileErrorM m) =>
(Namespace, Namespace)
-> [FilePath] -> m [WithVisibility (AnyCategory SourcePos)]
loadAllPublic (CompileMetadata -> Namespace
cmPublicNamespace CompileMetadata
dep,CompileMetadata -> Namespace
cmPrivateNamespace CompileMetadata
dep) [FilePath]
fs2
      let cs' :: [WithVisibility (AnyCategory SourcePos)]
cs' = if Bool -> Bool
not Bool
same
                   -- Allow ModuleOnly if the dep is the same module being
                   -- compiled. (Tests load the module being tested as a dep.)
                   then (WithVisibility (AnyCategory SourcePos) -> Bool)
-> [WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (WithVisibility (AnyCategory SourcePos) -> Bool)
-> WithVisibility (AnyCategory SourcePos)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodeVisibility -> WithVisibility (AnyCategory SourcePos) -> Bool
forall a. CodeVisibility -> WithVisibility a -> Bool
hasCodeVisibility CodeVisibility
ModuleOnly) [WithVisibility (AnyCategory SourcePos)]
cs
                   else [WithVisibility (AnyCategory SourcePos)]
cs
      [WithVisibility (AnyCategory SourcePos)]
-> m [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([WithVisibility (AnyCategory SourcePos)]
 -> m [WithVisibility (AnyCategory SourcePos)])
-> [WithVisibility (AnyCategory SourcePos)]
-> m [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> a -> b
$ (WithVisibility (AnyCategory SourcePos)
 -> WithVisibility (AnyCategory SourcePos))
-> [WithVisibility (AnyCategory SourcePos)]
-> [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> [a] -> [b]
map ((Set CodeVisibility -> Set CodeVisibility)
-> WithVisibility (AnyCategory SourcePos)
-> WithVisibility (AnyCategory SourcePos)
forall a.
(Set CodeVisibility -> Set CodeVisibility)
-> WithVisibility a -> WithVisibility a
updateCodeVisibility (Set CodeVisibility -> Set CodeVisibility -> Set CodeVisibility
forall a. Ord a => Set a -> Set a -> Set a
Set.union ([CodeVisibility] -> Set CodeVisibility
forall a. Ord a => [a] -> Set a
Set.fromList [CodeVisibility]
ss))) [WithVisibility (AnyCategory SourcePos)]
cs'
    loadAllPublic :: (Namespace, Namespace)
-> [FilePath] -> m [WithVisibility (AnyCategory SourcePos)]
loadAllPublic (Namespace
ns2,Namespace
ns3) [FilePath]
fs2 = do
      [(FilePath, FilePath)]
fs2' <- r -> FilePath -> [FilePath] -> m [(FilePath, FilePath)]
forall r (m :: * -> *).
(PathIOHandler r, MonadIO m, CompileErrorM m) =>
r -> FilePath -> [FilePath] -> m [(FilePath, FilePath)]
zipWithContents r
r FilePath
p [FilePath]
fs2
      ([[WithVisibility (AnyCategory SourcePos)]]
 -> [WithVisibility (AnyCategory SourcePos)])
-> m [[WithVisibility (AnyCategory SourcePos)]]
-> m [WithVisibility (AnyCategory SourcePos)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[WithVisibility (AnyCategory SourcePos)]]
-> [WithVisibility (AnyCategory SourcePos)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (m [[WithVisibility (AnyCategory SourcePos)]]
 -> m [WithVisibility (AnyCategory SourcePos)])
-> m [[WithVisibility (AnyCategory SourcePos)]]
-> m [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> a -> b
$ ((FilePath, FilePath)
 -> m [WithVisibility (AnyCategory SourcePos)])
-> [(FilePath, FilePath)]
-> m [[WithVisibility (AnyCategory SourcePos)]]
forall (m :: * -> *) a b.
CompileErrorM m =>
(a -> m b) -> [a] -> m [b]
mapErrorsM (FilePath, FilePath) -> m [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *).
CompileErrorM m =>
(FilePath, FilePath) -> m [WithVisibility (AnyCategory SourcePos)]
loadPublic [(FilePath, FilePath)]
fs2'
      where
        loadPublic :: (FilePath, FilePath) -> m [WithVisibility (AnyCategory SourcePos)]
loadPublic (FilePath, FilePath)
p3 = do
          ([Pragma SourcePos]
pragmas,[AnyCategory SourcePos]
cs) <- (FilePath, FilePath)
-> m ([Pragma SourcePos], [AnyCategory SourcePos])
forall (m :: * -> *).
CompileErrorM m =>
(FilePath, FilePath)
-> m ([Pragma SourcePos], [AnyCategory SourcePos])
parsePublicSource (FilePath, FilePath)
p3
          let tags :: Set CodeVisibility
tags = [CodeVisibility] -> Set CodeVisibility
forall a. Ord a => [a] -> Set a
Set.fromList ([CodeVisibility] -> Set CodeVisibility)
-> [CodeVisibility] -> Set CodeVisibility
forall a b. (a -> b) -> a -> b
$
                     (if (Pragma SourcePos -> Bool) -> [Pragma SourcePos] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Pragma SourcePos -> Bool
forall c. Pragma c -> Bool
isTestsOnly  [Pragma SourcePos]
pragmas then [CodeVisibility
TestsOnly]  else []) [CodeVisibility] -> [CodeVisibility] -> [CodeVisibility]
forall a. [a] -> [a] -> [a]
++
                     (if (Pragma SourcePos -> Bool) -> [Pragma SourcePos] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Pragma SourcePos -> Bool
forall c. Pragma c -> Bool
isModuleOnly [Pragma SourcePos]
pragmas then [CodeVisibility
ModuleOnly] else [])
          let cs' :: [AnyCategory SourcePos]
cs' = if (Pragma SourcePos -> Bool) -> [Pragma SourcePos] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Pragma SourcePos -> Bool
forall c. Pragma c -> Bool
isModuleOnly [Pragma SourcePos]
pragmas
                       then (AnyCategory SourcePos -> AnyCategory SourcePos)
-> [AnyCategory SourcePos] -> [AnyCategory SourcePos]
forall a b. (a -> b) -> [a] -> [b]
map (Namespace -> AnyCategory SourcePos -> AnyCategory SourcePos
forall c. Namespace -> AnyCategory c -> AnyCategory c
setCategoryNamespace Namespace
ns3) [AnyCategory SourcePos]
cs
                       else (AnyCategory SourcePos -> AnyCategory SourcePos)
-> [AnyCategory SourcePos] -> [AnyCategory SourcePos]
forall a b. (a -> b) -> [a] -> [b]
map (Namespace -> AnyCategory SourcePos -> AnyCategory SourcePos
forall c. Namespace -> AnyCategory c -> AnyCategory c
setCategoryNamespace Namespace
ns2) [AnyCategory SourcePos]
cs
          [WithVisibility (AnyCategory SourcePos)]
-> m [WithVisibility (AnyCategory SourcePos)]
forall (m :: * -> *) a. Monad m => a -> m a
return ([WithVisibility (AnyCategory SourcePos)]
 -> m [WithVisibility (AnyCategory SourcePos)])
-> [WithVisibility (AnyCategory SourcePos)]
-> m [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> a -> b
$ (AnyCategory SourcePos -> WithVisibility (AnyCategory SourcePos))
-> [AnyCategory SourcePos]
-> [WithVisibility (AnyCategory SourcePos)]
forall a b. (a -> b) -> [a] -> [b]
map (Set CodeVisibility
-> AnyCategory SourcePos -> WithVisibility (AnyCategory SourcePos)
forall a. Set CodeVisibility -> a -> WithVisibility a
WithVisibility Set CodeVisibility
tags) [AnyCategory SourcePos]
cs'