{- -----------------------------------------------------------------------------
Copyright 2020-2022 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,
  createCachedDir,
  createCachePath,
  eraseCachedData,
  findSourceFiles,
  getCachedPath,
  getCacheRelativePath,
  getExprMap,
  getIncludePathsForDeps,
  getLibrariesForDeps,
  getLinkFlagsForDeps,
  getNamespacesForDeps,
  getObjectFilesForDeps,
  getObjectFileResolver,
  getRealPathsForDeps,
  getRecompilePath,
  isPathConfigured,
  isPathUpToDate,
  isPrivateSource,
  isPublicSource,
  isTestSource,
  loadModuleGlobals,
  loadModuleMetadata,
  loadPrivateDeps,
  loadPublicDeps,
  loadRecompile,
  loadTestingDeps,
  mapMetadata,
  readPossibleTraces,
  resolveCategoryDeps,
  resolveObjectDeps,
  sortCompiledFiles,
  writeCachedFile,
  writeMetadata,
  writePossibleTraces,
  writeRecompile,
) where

import Control.Applicative ((<|>))
import Control.Monad (when)
import Data.List (isSuffixOf,nub)
import Data.Maybe (isJust)
import Data.Time.Clock (UTCTime)
import System.Directory
import System.FilePath
import System.IO
import qualified Data.Map as Map
import qualified Data.Set as Set

import Base.CompilerError
import Base.TrackedErrors
import Cli.CompileOptions
import Cli.Programs (VersionHash(..))
import Compilation.ProcedureContext (ExprMap)
import CompilerCxx.CxxFiles (CxxOutput(..))
import Module.CompileMetadata
import Module.ParseMetadata
import Module.Paths
import Parser.SourceFile
import Parser.TextParser (SourceContext)
import Types.Procedure
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"

tracesFilename :: FilePath
tracesFilename :: FilePath
tracesFilename = FilePath
"traced-lines"

isPublicSource :: FilePath -> Bool
isPublicSource :: FilePath -> Bool
isPublicSource = FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rp"

isPrivateSource :: FilePath -> Bool
isPrivateSource :: FilePath -> Bool
isPrivateSource = FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rx"

isTestSource :: FilePath -> Bool
isTestSource :: FilePath -> Bool
isTestSource = FilePath -> FilePath -> Bool
forall a. Eq a => [a] -> [a] -> Bool
isSuffixOf FilePath
".0rt"

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 -> TrackedErrorsIO ModuleConfig
loadRecompile :: FilePath -> TrackedErrorsIO ModuleConfig
loadRecompile FilePath
p = do
  let f :: FilePath
f = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename
  Bool
isFile <- IO Bool -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
p
  Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
p
  Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f
  Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
filePresent) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
readFile FilePath
f
  ModuleConfig
m <- FilePath -> FilePath -> TrackedErrorsIO ModuleConfig
forall a (m :: * -> *).
(ConfigFormat a, ErrorContextM m) =>
FilePath -> FilePath -> m a
autoReadConfig FilePath
f FilePath
c TrackedErrorsIO ModuleConfig
-> FilePath -> TrackedErrorsIO ModuleConfig
forall (m :: * -> *) a. ErrorContextM 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"
  FilePath
p0 <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  let p1 :: FilePath
p1 = ModuleConfig -> FilePath
mcRoot ModuleConfig
m FilePath -> FilePath -> FilePath
</> ModuleConfig -> FilePath
mcPath ModuleConfig
m
  FilePath
p2 <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath) -> FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
p0 FilePath -> FilePath -> FilePath
</> FilePath
p1
  Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (FilePath
p2 FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
/= FilePath
p0) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath
"Expected module path from " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
                                    FilePath
" to match " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
moduleFilename FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
                                    FilePath
" location but got " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p2 FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
                                    FilePath
" (resolved from root: \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ModuleConfig -> FilePath
mcRoot ModuleConfig
m FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++
                                    FilePath
"\" and path: \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ ModuleConfig -> FilePath
mcPath ModuleConfig
m FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\")"
  ModuleConfig -> TrackedErrorsIO ModuleConfig
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ModuleConfig
m

isPathUpToDate :: VersionHash -> ForceMode -> FilePath -> TrackedErrorsIO Bool
isPathUpToDate :: VersionHash -> ForceMode -> FilePath -> TrackedErrorsT IO Bool
isPathUpToDate VersionHash
h ForceMode
f FilePath
p = do
  TrackedErrors [CompileMetadata]
m <- IO (TrackedErrors [CompileMetadata])
-> TrackedErrorsT IO (TrackedErrors [CompileMetadata])
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO (TrackedErrors [CompileMetadata])
 -> TrackedErrorsT IO (TrackedErrors [CompileMetadata]))
-> IO (TrackedErrors [CompileMetadata])
-> TrackedErrorsT IO (TrackedErrors [CompileMetadata])
forall a b. (a -> b) -> a -> b
$ TrackedErrorsT IO [CompileMetadata]
-> IO (TrackedErrors [CompileMetadata])
forall (m :: * -> *) a.
Monad m =>
TrackedErrorsT m a -> m (TrackedErrors a)
toTrackedErrors (TrackedErrorsT IO [CompileMetadata]
 -> IO (TrackedErrors [CompileMetadata]))
-> TrackedErrorsT IO [CompileMetadata]
-> IO (TrackedErrors [CompileMetadata])
forall a b. (a -> b) -> a -> b
$ ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT 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 -> TrackedErrorsT IO Bool
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> TrackedErrorsT IO Bool) -> Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ TrackedErrors [CompileMetadata] -> Bool
forall (t :: (* -> *) -> * -> *) a.
(ErrorContextT t, ErrorContextM (t Identity)) =>
t Identity a -> Bool
isCompilerError TrackedErrors [CompileMetadata]
m

isPathConfigured :: FilePath -> FilePath -> TrackedErrorsIO Bool
isPathConfigured :: FilePath -> FilePath -> TrackedErrorsT IO Bool
isPathConfigured FilePath
p FilePath
d = do
  TrackedErrors ModuleConfig
m <- IO (TrackedErrors ModuleConfig)
-> TrackedErrorsT IO (TrackedErrors ModuleConfig)
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO (TrackedErrors ModuleConfig)
 -> TrackedErrorsT IO (TrackedErrors ModuleConfig))
-> IO (TrackedErrors ModuleConfig)
-> TrackedErrorsT IO (TrackedErrors ModuleConfig)
forall a b. (a -> b) -> a -> b
$ TrackedErrorsIO ModuleConfig -> IO (TrackedErrors ModuleConfig)
forall (m :: * -> *) a.
Monad m =>
TrackedErrorsT m a -> m (TrackedErrors a)
toTrackedErrors (TrackedErrorsIO ModuleConfig -> IO (TrackedErrors ModuleConfig))
-> TrackedErrorsIO ModuleConfig -> IO (TrackedErrors ModuleConfig)
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsIO ModuleConfig
loadRecompile (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
d)
  Bool -> TrackedErrorsT IO Bool
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> TrackedErrorsT IO Bool) -> Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ TrackedErrors ModuleConfig -> Bool
forall (t :: (* -> *) -> * -> *) a.
(ErrorContextT t, ErrorContextM (t Identity)) =>
t Identity a -> Bool
isCompilerError TrackedErrors ModuleConfig
m

writeMetadata :: FilePath -> CompileMetadata -> UTCTime -> TrackedErrorsIO ()
writeMetadata :: FilePath -> CompileMetadata -> UTCTime -> TrackedErrorsT IO ()
writeMetadata FilePath
p CompileMetadata
m UTCTime
t = do
  FilePath
p' <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT 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 -> TrackedErrorsT IO FilePath
forall a (m :: * -> *).
(ConfigFormat a, CollectErrorsM m) =>
a -> m FilePath
autoWriteConfig CompileMetadata
m TrackedErrorsT IO FilePath
-> FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. ErrorContextM m => m a -> FilePath -> m a
<?? FilePath
"In data for " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p
  FilePath
-> FilePath
-> FilePath
-> Maybe UTCTime
-> FilePath
-> TrackedErrorsT IO ()
writeCachedFile FilePath
p' FilePath
"" FilePath
metadataFilename (UTCTime -> Maybe UTCTime
forall a. a -> Maybe a
Just UTCTime
t) FilePath
m'

writeRecompile :: FilePath -> ModuleConfig -> TrackedErrorsIO ()
writeRecompile :: FilePath -> ModuleConfig -> TrackedErrorsT IO ()
writeRecompile FilePath
p ModuleConfig
m = do
  FilePath
p' <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT 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 () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT 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 -> TrackedErrorsT IO FilePath
forall a (m :: * -> *).
(ConfigFormat a, CollectErrorsM m) =>
a -> m FilePath
autoWriteConfig ModuleConfig
m TrackedErrorsT IO FilePath
-> FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. ErrorContextM m => m a -> FilePath -> m a
<?? FilePath
"In data for " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p
  IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
writeFile FilePath
f FilePath
m'

writePossibleTraces :: FilePath -> Set.Set String -> TrackedErrorsIO ()
writePossibleTraces :: FilePath -> Set FilePath -> TrackedErrorsT IO ()
writePossibleTraces FilePath
p Set FilePath
ts = do
  FilePath
p' <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  FilePath
-> FilePath
-> FilePath
-> Maybe UTCTime
-> FilePath
-> TrackedErrorsT IO ()
writeCachedFile FilePath
p' FilePath
"" FilePath
tracesFilename Maybe UTCTime
forall a. Maybe a
Nothing (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT IO ()
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 -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++FilePath
"\n") ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ Set FilePath -> [FilePath]
forall a. Set a -> [a]
Set.toList Set FilePath
ts

readPossibleTraces :: FilePath -> TrackedErrorsIO (Set.Set String)
readPossibleTraces :: FilePath -> TrackedErrorsIO (Set FilePath)
readPossibleTraces FilePath
p = do
  FilePath
p' <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  FilePath
c <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
readFile (FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p' FilePath
"" FilePath
tracesFilename)
  Set FilePath -> TrackedErrorsIO (Set FilePath)
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Set FilePath -> TrackedErrorsIO (Set FilePath))
-> Set FilePath -> TrackedErrorsIO (Set FilePath)
forall a b. (a -> b) -> a -> b
$ [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
$ FilePath -> [FilePath]
lines FilePath
c

getRecompilePath :: FilePath -> TrackedErrorsIO FilePath
getRecompilePath :: FilePath -> TrackedErrorsT IO FilePath
getRecompilePath FilePath
p = do
  FilePath
p' <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
  FilePath -> TrackedErrorsT IO FilePath
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> TrackedErrorsT IO FilePath)
-> FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
p' FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename

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

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

createCachedDir :: FilePath -> FilePath -> TrackedErrorsIO FilePath
createCachedDir :: FilePath -> FilePath -> TrackedErrorsT IO FilePath
createCachedDir FilePath
p FilePath
d = do
  FilePath -> TrackedErrorsT IO ()
createCachePath FilePath
p
  let d2 :: FilePath
d2 = FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
cachedDataPath FilePath -> FilePath -> FilePath
</> FilePath
d
  IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath -> IO ()
createDirectoryIfMissing Bool
False FilePath
d2
  FilePath -> TrackedErrorsT IO FilePath
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
d2

writeCachedFile :: FilePath -> String -> FilePath -> Maybe UTCTime -> String -> TrackedErrorsIO ()
writeCachedFile :: FilePath
-> FilePath
-> FilePath
-> Maybe UTCTime
-> FilePath
-> TrackedErrorsT IO ()
writeCachedFile FilePath
p FilePath
ns FilePath
f Maybe UTCTime
t FilePath
c = do
  FilePath -> TrackedErrorsT IO ()
createCachePath FilePath
p
  IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT 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
  let filename :: FilePath
filename = FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
p FilePath
ns FilePath
f
  IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath -> IO ()
writeFile FilePath
filename FilePath
c
  case Maybe UTCTime
t of
       Just UTCTime
t2 -> IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> UTCTime -> IO ()
setModificationTime FilePath
filename UTCTime
t2
       Maybe UTCTime
Nothing -> () -> TrackedErrorsT IO ()
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()

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] -> TrackedErrorsIO ([FilePath],[FilePath],[FilePath])
findSourceFiles :: FilePath
-> [FilePath]
-> TrackedErrorsIO ([FilePath], [FilePath], [FilePath])
findSourceFiles FilePath
p0 = ([[FilePath]] -> ([FilePath], [FilePath], [FilePath]))
-> TrackedErrorsT IO [[FilePath]]
-> TrackedErrorsIO ([FilePath], [FilePath], [FilePath])
forall a b. (a -> b) -> TrackedErrorsT IO a -> TrackedErrorsT IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([FilePath] -> ([FilePath], [FilePath], [FilePath])
select ([FilePath] -> ([FilePath], [FilePath], [FilePath]))
-> ([[FilePath]] -> [FilePath])
-> [[FilePath]]
-> ([FilePath], [FilePath], [FilePath])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat) (TrackedErrorsT IO [[FilePath]]
 -> TrackedErrorsIO ([FilePath], [FilePath], [FilePath]))
-> ([FilePath] -> TrackedErrorsT IO [[FilePath]])
-> [FilePath]
-> TrackedErrorsIO ([FilePath], [FilePath], [FilePath])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath -> TrackedErrorsT IO [FilePath])
-> [FilePath] -> TrackedErrorsT IO [[FilePath]]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM FilePath -> TrackedErrorsT IO [FilePath]
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m [FilePath]
find where
  find :: FilePath -> m [FilePath]
find FilePath
p = do
    let absolute :: FilePath
absolute = FilePath
p0 FilePath -> FilePath -> FilePath
</> FilePath
p
    Bool
isFile <- IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM 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
absolute
    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m ()
forall a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> m ()) -> FilePath -> m ()
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 -> m Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM 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
absolute
    Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FilePath -> m ()
forall a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> m ()) -> FilePath -> m ()
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"
    IO [FilePath] -> m [FilePath]
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO [FilePath] -> m [FilePath]) -> IO [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO [FilePath]
getDirectoryContents FilePath
absolute IO [FilePath] -> ([FilePath] -> IO [FilePath]) -> IO [FilePath]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [FilePath] -> IO [FilePath]
forall a. a -> IO a
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
</>)
  select :: [FilePath] -> ([FilePath], [FilePath], [FilePath])
select [FilePath]
ds = ([FilePath]
ps,[FilePath]
xs,[FilePath]
ts) where
    ps :: [FilePath]
ps = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
isPublicSource  [FilePath]
ds
    xs :: [FilePath]
xs = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
isPrivateSource [FilePath]
ds
    ts :: [FilePath]
ts = [FilePath] -> [FilePath]
forall a. Eq a => [a] -> [a]
nub ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
isTestSource    [FilePath]
ds

getExprMap :: FilePath -> ModuleConfig -> TrackedErrorsIO (ExprMap SourceContext)
getExprMap :: FilePath -> ModuleConfig -> TrackedErrorsIO (ExprMap SourceContext)
getExprMap FilePath
p ModuleConfig
m = do
  FilePath
path <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT 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 :: [(MacroName, Expression c)]
defaults = [(FilePath -> MacroName
MacroName 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 SourceContext -> TrackedErrorsIO (ExprMap SourceContext)
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (ExprMap SourceContext -> TrackedErrorsIO (ExprMap SourceContext))
-> ExprMap SourceContext -> TrackedErrorsIO (ExprMap SourceContext)
forall a b. (a -> b) -> a -> b
$ [(MacroName, Expression SourceContext)] -> ExprMap SourceContext
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(MacroName, Expression SourceContext)] -> ExprMap SourceContext)
-> [(MacroName, Expression SourceContext)] -> ExprMap SourceContext
forall a b. (a -> b) -> a -> b
$ ModuleConfig -> [(MacroName, Expression SourceContext)]
mcExprMap ModuleConfig
m [(MacroName, Expression SourceContext)]
-> [(MacroName, Expression SourceContext)]
-> [(MacroName, Expression SourceContext)]
forall a. [a] -> [a] -> [a]
++ [(MacroName, Expression SourceContext)]
forall {c}. [(MacroName, 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,[FilePath])]
getSourceFilesForDeps :: [CompileMetadata] -> [(FilePath, [FilePath])]
getSourceFilesForDeps = (CompileMetadata -> (FilePath, [FilePath]))
-> [CompileMetadata] -> [(FilePath, [FilePath])]
forall a b. (a -> b) -> [a] -> [b]
map CompileMetadata -> (FilePath, [FilePath])
extract where
  extract :: CompileMetadata -> (FilePath, [FilePath])
extract CompileMetadata
m = (CompileMetadata -> FilePath
cmRoot CompileMetadata
m,(FilePath -> Bool) -> [FilePath] -> [FilePath]
forall a. (a -> Bool) -> [a] -> [a]
filter FilePath -> Bool
isPublicSource ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ CompileMetadata -> [FilePath]
cmPublicFiles CompileMetadata
m [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ CompileMetadata -> [FilePath]
cmPrivateFiles 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

getLibrariesForDeps :: [CompileMetadata] -> [FilePath]
getLibrariesForDeps :: [CompileMetadata] -> [FilePath]
getLibrariesForDeps = [[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]
cmLibraries

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 ->
  TrackedErrorsIO CompileMetadata
loadModuleMetadata :: VersionHash
-> ForceMode
-> MetadataMap
-> FilePath
-> TrackedErrorsIO CompileMetadata
loadModuleMetadata VersionHash
h ForceMode
f MetadataMap
ca = ([CompileMetadata] -> CompileMetadata)
-> TrackedErrorsT IO [CompileMetadata]
-> TrackedErrorsIO CompileMetadata
forall a b. (a -> b) -> TrackedErrorsT IO a -> TrackedErrorsT IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [CompileMetadata] -> CompileMetadata
forall a. HasCallStack => [a] -> a
head (TrackedErrorsT IO [CompileMetadata]
 -> TrackedErrorsIO CompileMetadata)
-> (FilePath -> TrackedErrorsT IO [CompileMetadata])
-> FilePath
-> TrackedErrorsIO CompileMetadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT 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] -> TrackedErrorsT IO [CompileMetadata])
-> (FilePath -> [FilePath])
-> FilePath
-> TrackedErrorsT 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] ->
  TrackedErrorsIO [CompileMetadata]
loadPublicDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> [FilePath]
-> TrackedErrorsT IO [CompileMetadata]
loadPublicDeps VersionHash
h ForceMode
f MetadataMap
ca = ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT 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 ->
  TrackedErrorsIO [CompileMetadata]
loadTestingDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> CompileMetadata
-> TrackedErrorsT IO [CompileMetadata]
loadTestingDeps VersionHash
h ForceMode
f MetadataMap
ca CompileMetadata
m = ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT 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] ->
  TrackedErrorsIO [CompileMetadata]
loadPrivateDeps :: VersionHash
-> ForceMode
-> MetadataMap
-> [CompileMetadata]
-> TrackedErrorsT IO [CompileMetadata]
loadPrivateDeps VersionHash
h ForceMode
f MetadataMap
ca [CompileMetadata]
ms = do
  [CompileMetadata]
new <- ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT 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] -> TrackedErrorsT IO [CompileMetadata]
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([CompileMetadata] -> TrackedErrorsT IO [CompileMetadata])
-> [CompileMetadata] -> TrackedErrorsT 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] -> TrackedErrorsIO [CompileMetadata]
loadDepsCommon :: ForceMode
-> VersionHash
-> MetadataMap
-> Set FilePath
-> (CompileMetadata -> [FilePath])
-> [FilePath]
-> TrackedErrorsT IO [CompileMetadata]
loadDepsCommon ForceMode
f VersionHash
h MetadataMap
ca Set FilePath
pa0 CompileMetadata -> [FilePath]
getDeps [FilePath]
ps = do
  (Set FilePath
_,[(FilePath, CompileMetadata)]
processed) <- TrackedErrorsT IO [FilePath]
fixedPaths TrackedErrorsT IO [FilePath]
-> ([FilePath]
    -> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)]))
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
forall a b.
TrackedErrorsT IO a
-> (a -> TrackedErrorsT IO b) -> TrackedErrorsT IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> TrackedErrorsT 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) -> TrackedErrorsIO CompileMetadata)
-> [(FilePath, CompileMetadata)]
-> TrackedErrorsT IO [CompileMetadata]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (MetadataMap
-> (FilePath, CompileMetadata) -> TrackedErrorsIO CompileMetadata
forall {m :: * -> *}.
MonadIO m =>
MetadataMap
-> (FilePath, CompileMetadata) -> TrackedErrorsT 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 :: TrackedErrorsT IO [FilePath]
fixedPaths = (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath) [FilePath]
ps
    collect :: (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> TrackedErrorsT 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]
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
collect (Set FilePath, [(FilePath, CompileMetadata)])
xa [FilePath]
ps2
      | Bool
otherwise = do
          let continue :: CompileMetadata
-> [FilePath]
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m [FilePath]
ds = (Set FilePath, [(FilePath, CompileMetadata)])
-> [FilePath]
-> TrackedErrorsT 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]
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m2 []
               Maybe CompileMetadata
Nothing -> do
                 IO () -> TrackedErrorsT IO ()
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO () -> TrackedErrorsT IO ()) -> IO () -> TrackedErrorsT 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 module \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
p FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\"."
                 CompileMetadata
m2 <- MetadataMap -> FilePath -> TrackedErrorsIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
p
                 let ds :: [FilePath]
ds = CompileMetadata -> [FilePath]
getDeps CompileMetadata
m2
                 CompileMetadata
-> [FilePath]
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
continue CompileMetadata
m2 [FilePath]
ds
    collect (Set FilePath, [(FilePath, CompileMetadata)])
xa [FilePath]
_ = (Set FilePath, [(FilePath, CompileMetadata)])
-> TrackedErrorsT IO (Set FilePath, [(FilePath, CompileMetadata)])
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Set FilePath, [(FilePath, CompileMetadata)])
xa
    check :: MetadataMap
-> (FilePath, CompileMetadata) -> TrackedErrorsT 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 -> TrackedErrorsT m CompileMetadata
forall a. a -> TrackedErrorsT m a
forall (m :: * -> *) a. Monad m => a -> m a
return CompileMetadata
m
      | Bool
otherwise = do
          FilePath
p' <- IO FilePath -> TrackedErrorsT m FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT m FilePath)
-> IO FilePath -> TrackedErrorsT m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath FilePath
p
          Bool -> TrackedErrorsT m () -> TrackedErrorsT 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') (TrackedErrorsT m () -> TrackedErrorsT m ())
-> TrackedErrorsT m () -> TrackedErrorsT m ()
forall a b. (a -> b) -> a -> b
$
            FilePath -> TrackedErrorsT m ()
forall a. FilePath -> TrackedErrorsT m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT m ())
-> FilePath -> TrackedErrorsT 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"
          TrackedErrors ()
fresh <- IO (TrackedErrors ()) -> TrackedErrorsT m (TrackedErrors ())
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO (TrackedErrors ()) -> TrackedErrorsT m (TrackedErrors ()))
-> IO (TrackedErrors ()) -> TrackedErrorsT m (TrackedErrors ())
forall a b. (a -> b) -> a -> b
$ TrackedErrorsT IO () -> IO (TrackedErrors ())
forall (m :: * -> *) a.
Monad m =>
TrackedErrorsT m a -> m (TrackedErrors a)
toTrackedErrors (TrackedErrorsT IO () -> IO (TrackedErrors ()))
-> TrackedErrorsT IO () -> IO (TrackedErrors ())
forall a b. (a -> b) -> a -> b
$ VersionHash
-> MetadataMap
-> FilePath
-> CompileMetadata
-> TrackedErrorsT IO ()
checkModuleFreshness VersionHash
h MetadataMap
cm FilePath
p CompileMetadata
m TrackedErrorsT IO () -> FilePath -> TrackedErrorsT IO ()
forall (m :: * -> *) a. ErrorContextM 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 TrackedErrors () -> TrackedErrorsT m ()
forall (m :: * -> *) a.
Monad m =>
TrackedErrors a -> TrackedErrorsT m a
fromTrackedErrors   TrackedErrors ()
fresh
             else TrackedErrors () -> TrackedErrorsT m ()
forall (m :: * -> *) a.
Monad m =>
TrackedErrors a -> TrackedErrorsT m ()
asCompilerWarnings TrackedErrors ()
fresh
          CompileMetadata -> TrackedErrorsT m CompileMetadata
forall a. a -> TrackedErrorsT m a
forall (m :: * -> *) a. Monad m => a -> m a
return CompileMetadata
m

loadMetadata :: MetadataMap -> FilePath -> TrackedErrorsIO CompileMetadata
loadMetadata :: MetadataMap -> FilePath -> TrackedErrorsIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
p = do
  FilePath
path <- IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT 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 -> TrackedErrorsIO CompileMetadata
forall a. a -> TrackedErrorsT IO a
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 -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
p
         Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isFile (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesDirectoryExist FilePath
p
         Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
isDir) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO Bool -> TrackedErrorsT IO Bool)
-> IO Bool -> TrackedErrorsT IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath -> IO Bool
doesFileExist FilePath
f
         Bool -> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not Bool
filePresent) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> IO FilePath -> TrackedErrorsT IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
readFile FilePath
f
         (FilePath -> FilePath -> TrackedErrorsIO CompileMetadata
forall a (m :: * -> *).
(ConfigFormat a, ErrorContextM m) =>
FilePath -> FilePath -> m a
autoReadConfig FilePath
f FilePath
c) TrackedErrorsIO CompileMetadata
-> FilePath -> TrackedErrorsIO CompileMetadata
forall (m :: * -> *) a. ErrorContextM 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 b a. (b -> a -> b) -> b -> [a] -> b
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 -> TrackedErrorsIO ()
checkModuleFreshness :: VersionHash
-> MetadataMap
-> FilePath
-> CompileMetadata
-> TrackedErrorsT IO ()
checkModuleFreshness VersionHash
h MetadataMap
ca FilePath
p m :: CompileMetadata
m@(CompileMetadata VersionHash
_ FilePath
p2 FilePath
d [FilePath]
ep Namespace
_ Namespace
_ [FilePath]
is [FilePath]
is2 [CategoryName]
_ [CategoryName]
_ [FilePath]
_ [FilePath]
_ [FilePath]
ps [FilePath]
xs [FilePath]
ts [FilePath]
hxx [FilePath]
cxx [FilePath]
bs [FilePath]
ls [FilePath]
_ [ObjectFile]
os) = do
  UTCTime
time <- IO UTCTime -> TrackedErrorsT IO UTCTime
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO UTCTime -> TrackedErrorsT IO UTCTime)
-> IO UTCTime -> TrackedErrorsT 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]
-> TrackedErrorsIO ([FilePath], [FilePath], [FilePath])
findSourceFiles FilePath
p2 (FilePath
dFilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
:[FilePath]
ep)
  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
  [FilePath]
expectedFiles <- (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath)
-> (FilePath -> FilePath) -> FilePath -> IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
p2FilePath -> FilePath -> FilePath
</>)) ([FilePath]
ps[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath]
xs[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath]
ts)
  [FilePath]
actualFiles   <- (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath)
-> (FilePath -> FilePath) -> FilePath -> IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
p2FilePath -> FilePath -> FilePath
</>)) ([FilePath]
ps2[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath]
xs2[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath]
ts2)
  [FilePath]
inputFiles    <- (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath)
-> (FilePath -> FilePath) -> FilePath -> IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
p2FilePath -> FilePath -> FilePath
</>)) ([FilePath]
ps[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++[FilePath]
xs)
  [FilePath]
testFiles     <- (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath)
-> (FilePath -> FilePath) -> FilePath -> IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (FilePath
p2FilePath -> FilePath -> FilePath
</>)) [FilePath]
ts
  [TrackedErrorsT IO ()] -> TrackedErrorsT IO ()
forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, CollectErrorsM m) =>
f (m a) -> m ()
collectAllM_ ([TrackedErrorsT IO ()] -> TrackedErrorsT IO ())
-> [TrackedErrorsT IO ()] -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$ [
      TrackedErrorsT IO ()
checkHash,
      UTCTime -> FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
moduleFilename),
      [FilePath] -> [FilePath] -> TrackedErrorsT IO ()
forall {m :: * -> *}.
CollectErrorsM m =>
[FilePath] -> [FilePath] -> m ()
checkMissing [FilePath]
expectedFiles [FilePath]
actualFiles
    ] [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> TrackedErrorsT IO ()
checkDep UTCTime
time) ([FilePath] -> [TrackedErrorsT IO ()])
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> a -> b
$ [FilePath]
is [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
is2) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time) [FilePath]
inputFiles) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m ()
checkPresent [FilePath]
testFiles) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map (UTCTime -> FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time (FilePath -> TrackedErrorsT IO ())
-> (FilePath -> FilePath) -> FilePath -> TrackedErrorsT IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath -> FilePath -> FilePath
getCachedPath FilePath
d FilePath
"") ([FilePath] -> [TrackedErrorsT IO ()])
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> a -> b
$ [FilePath]
hxx [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
cxx) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m ()
checkOutput [FilePath]
bs) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m ()
checkOutput [FilePath]
ls) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((ObjectFile -> TrackedErrorsT IO ())
-> [ObjectFile] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map ObjectFile -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
ObjectFile -> m ()
checkObject [ObjectFile]
os) [TrackedErrorsT IO ()]
-> [TrackedErrorsT IO ()] -> [TrackedErrorsT IO ()]
forall a. [a] -> [a] -> [a]
++
    ((CategoryIdentifier -> TrackedErrorsT IO ())
-> [CategoryIdentifier] -> [TrackedErrorsT IO ()]
forall a b. (a -> b) -> [a] -> [b]
map CategoryIdentifier -> TrackedErrorsT IO ()
checkRequire [CategoryIdentifier]
rs)
  where
    checkHash :: TrackedErrorsT IO ()
checkHash =
      Bool -> TrackedErrorsT IO () -> TrackedErrorsT 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) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$
        FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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"
    checkPresent :: FilePath -> m ()
checkPresent FilePath
f = do
      Bool
exists <- FilePath -> m Bool
forall {m :: * -> *}.
(MonadIO m, ErrorContextM 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 a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (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"
    checkInput :: UTCTime -> FilePath -> m ()
checkInput UTCTime
time FilePath
f = do
      Bool
exists <- FilePath -> m Bool
forall {m :: * -> *}.
(MonadIO m, ErrorContextM 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 a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (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, ErrorContextM 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 a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (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, ErrorContextM 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 a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (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 -> TrackedErrorsT IO ()
checkDep UTCTime
time FilePath
dep = do
      CompileMetadata
cm <- MetadataMap -> FilePath -> TrackedErrorsIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
dep
      [FilePath]
files <- (FilePath -> TrackedErrorsT IO FilePath)
-> [FilePath] -> TrackedErrorsT IO [FilePath]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (IO FilePath -> TrackedErrorsT IO FilePath
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO FilePath -> TrackedErrorsT IO FilePath)
-> (FilePath -> IO FilePath)
-> FilePath
-> TrackedErrorsT IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath)
-> (FilePath -> FilePath) -> FilePath -> IO FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CompileMetadata -> FilePath
cmRoot CompileMetadata
cm FilePath -> FilePath -> FilePath
</>)) (CompileMetadata -> [FilePath]
cmPublicFiles CompileMetadata
cm)
      (FilePath -> TrackedErrorsT IO ())
-> [FilePath] -> TrackedErrorsT IO ()
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m ()
mapCompilerM_ (UTCTime -> FilePath -> TrackedErrorsT IO ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
UTCTime -> FilePath -> m ()
checkInput UTCTime
time) [FilePath]
files
    checkObject :: ObjectFile -> m ()
checkObject (CategoryObjectFile CategoryIdentifier
_ [CategoryIdentifier]
_ [FilePath]
fs) = (FilePath -> m ()) -> [FilePath] -> m ()
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m ()
mapCompilerM_ FilePath -> m ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m ()
checkOutput [FilePath]
fs
    checkObject (OtherObjectFile FilePath
f)         = FilePath -> m ()
forall {m :: * -> *}.
(MonadIO m, ErrorContextM m) =>
FilePath -> m ()
checkOutput FilePath
f
    getRequires :: ObjectFile -> [CategoryIdentifier]
getRequires (CategoryObjectFile CategoryIdentifier
_ [CategoryIdentifier]
rs [FilePath]
_) = [CategoryIdentifier]
rs
    getRequires ObjectFile
_                           = []
    checkRequire :: CategoryIdentifier -> TrackedErrorsT IO ()
checkRequire (CategoryIdentifier FilePath
d2 CategoryName
c Namespace
ns) = do
      CompileMetadata
cm <- MetadataMap -> FilePath -> TrackedErrorsIO CompileMetadata
loadMetadata MetadataMap
ca FilePath
d2
      Bool -> TrackedErrorsT IO () -> TrackedErrorsT 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
d Bool -> Bool -> Bool
&& Namespace
ns Namespace -> Namespace -> Bool
forall a. Eq a => a -> a -> Bool
/= CompileMetadata -> Namespace
cmPublicNamespace CompileMetadata
cm) (TrackedErrorsT IO () -> TrackedErrorsT IO ())
-> TrackedErrorsT IO () -> TrackedErrorsT IO ()
forall a b. (a -> b) -> a -> b
$
        FilePath -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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 -> TrackedErrorsT IO ()
forall a. FilePath -> TrackedErrorsT IO a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> TrackedErrorsT IO ())
-> FilePath -> TrackedErrorsT 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.
CollectErrorsM m =>
(a -> m b) -> [a] -> m ()
mapCompilerM_ (\FilePath
f -> FilePath -> m Any
forall a. FilePath -> m a
forall (m :: * -> *) a. ErrorContextM m => FilePath -> m a
compilerErrorM (FilePath -> m Any) -> FilePath -> m Any
forall a b. (a -> b) -> a -> b
$ FilePath
"Input path \"" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
f FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"\" is not present in cached data") [FilePath]
missing
    doesFileOrDirExist :: FilePath -> m Bool
doesFileOrDirExist FilePath
f2 = do
      Bool
existF <- IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM 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 a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
        else IO Bool -> m Bool
forall (m :: * -> *) a. (MonadIO m, ErrorContextM 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] -> Set.Set Namespace -> Set.Set CategoryName -> [FilePath]
getObjectFileResolver :: [ObjectFile] -> Set Namespace -> Set CategoryName -> [FilePath]
getObjectFileResolver [ObjectFile]
os Set Namespace
ns Set 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] -> [[ObjectFile]])
-> [CategoryName] -> [[ObjectFile]]
forall a b. (a -> b) -> a -> b
$ Set CategoryName -> [CategoryName]
forall a. Set a -> [a]
Set.toList Set 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 b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Maybe [ObjectFile] -> Maybe [ObjectFile] -> Maybe [ObjectFile]
forall a. Maybe a -> Maybe a -> Maybe a
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 a. Maybe a -> Maybe a -> Maybe a
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 a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [ObjectFile] -> Maybe [ObjectFile]
forall a. a -> Maybe a
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]
:[])) (Set Namespace -> [Namespace]
forall a. Set a -> [a]
Set.toList Set 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 a. Eq a => a -> Set a -> 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 Set Namespace
_ Set CategoryName
_ Set FilePath
_ [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
_ Set Namespace
ns2 Set CategoryName
ds Set FilePath
_ [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 (Set Namespace -> [Namespace]
forall a. Set a -> [a]
Set.toList Set Namespace
ns2 [Namespace] -> [Namespace] -> [Namespace]
forall a. [a] -> [a] -> [a]
++ [Namespace]
publicNamespaces)) ([CategoryName] -> [[CategoryIdentifier]])
-> [CategoryName] -> [[CategoryIdentifier]]
forall a b. (a -> b) -> a -> b
$ Set CategoryName -> [CategoryName]
forall a. Set a -> [a]
Set.toList Set 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] ->
  TrackedErrorsIO ([WithVisibility (AnyCategory SourceContext)],Set.Set FilePath)
loadModuleGlobals :: forall r.
PathIOHandler r =>
r
-> FilePath
-> (Namespace, Namespace)
-> [FilePath]
-> Maybe CompileMetadata
-> [CompileMetadata]
-> [CompileMetadata]
-> TrackedErrorsIO
     ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
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 SourceContext)]
cs0 <- ([[WithVisibility (AnyCategory SourceContext)]]
 -> [WithVisibility (AnyCategory SourceContext)])
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> TrackedErrorsT IO a -> TrackedErrorsT IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[WithVisibility (AnyCategory SourceContext)]]
-> [WithVisibility (AnyCategory SourceContext)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
 -> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)])
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata
 -> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)])
-> [CompileMetadata]
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (Bool
-> [CodeVisibility]
-> CompileMetadata
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourceContext)]
processDeps Bool
False [CodeVisibility
FromDependency])            [CompileMetadata]
deps1
  [WithVisibility (AnyCategory SourceContext)]
cs1 <- ([[WithVisibility (AnyCategory SourceContext)]]
 -> [WithVisibility (AnyCategory SourceContext)])
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> TrackedErrorsT IO a -> TrackedErrorsT IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[WithVisibility (AnyCategory SourceContext)]]
-> [WithVisibility (AnyCategory SourceContext)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
 -> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)])
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> a -> b
$ (CompileMetadata
 -> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)])
-> [CompileMetadata]
-> TrackedErrorsT IO [[WithVisibility (AnyCategory SourceContext)]]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (Bool
-> [CodeVisibility]
-> CompileMetadata
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourceContext)]
processDeps Bool
False [CodeVisibility
FromDependency,CodeVisibility
ModuleOnly]) [CompileMetadata]
deps2'
  ([WithVisibility (AnyCategory SourceContext)]
cs2,Set FilePath
xa) <- (Namespace, Namespace)
-> [(FilePath, [FilePath])]
-> TrackedErrorsIO
     ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
(Namespace, Namespace)
-> [(FilePath, [FilePath])]
-> m ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
loadAllPublic (Namespace
ns0,Namespace
ns1) [(FilePath
p,[FilePath]
fs)]
  [WithVisibility (AnyCategory SourceContext)]
cs3 <- case Maybe CompileMetadata
m of
              Just CompileMetadata
m2 -> Bool
-> [CodeVisibility]
-> CompileMetadata
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourceContext)]
processDeps Bool
True [CodeVisibility
FromDependency] CompileMetadata
m2
              Maybe CompileMetadata
_       -> [WithVisibility (AnyCategory SourceContext)]
-> TrackedErrorsT IO [WithVisibility (AnyCategory SourceContext)]
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
  ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
-> TrackedErrorsIO
     ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
forall a. a -> TrackedErrorsT IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([WithVisibility (AnyCategory SourceContext)]
cs0[WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourceContext)]
cs1[WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourceContext)]
cs2[WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
forall a. [a] -> [a] -> [a]
++[WithVisibility (AnyCategory SourceContext)]
cs3,Set FilePath
xa) where
    processDeps :: Bool
-> [CodeVisibility]
-> CompileMetadata
-> m [WithVisibility (AnyCategory SourceContext)]
processDeps Bool
same [CodeVisibility]
ss CompileMetadata
dep = do
      let fs2 :: [(FilePath, [FilePath])]
fs2 = [CompileMetadata] -> [(FilePath, [FilePath])]
getSourceFilesForDeps [CompileMetadata
dep]
      ([WithVisibility (AnyCategory SourceContext)]
cs,Set FilePath
_) <- (Namespace, Namespace)
-> [(FilePath, [FilePath])]
-> m ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
forall {m :: * -> *}.
(CollectErrorsM m, MonadIO m) =>
(Namespace, Namespace)
-> [(FilePath, [FilePath])]
-> m ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
loadAllPublic (CompileMetadata -> Namespace
cmPublicNamespace CompileMetadata
dep,CompileMetadata -> Namespace
cmPrivateNamespace CompileMetadata
dep) [(FilePath, [FilePath])]
fs2
      let cs' :: [WithVisibility (AnyCategory SourceContext)]
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 SourceContext) -> Bool)
-> [WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (WithVisibility (AnyCategory SourceContext) -> Bool)
-> WithVisibility (AnyCategory SourceContext)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CodeVisibility
-> WithVisibility (AnyCategory SourceContext) -> Bool
forall a. CodeVisibility -> WithVisibility a -> Bool
hasCodeVisibility CodeVisibility
ModuleOnly) [WithVisibility (AnyCategory SourceContext)]
cs
                   else [WithVisibility (AnyCategory SourceContext)]
cs
      [WithVisibility (AnyCategory SourceContext)]
-> m [WithVisibility (AnyCategory SourceContext)]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([WithVisibility (AnyCategory SourceContext)]
 -> m [WithVisibility (AnyCategory SourceContext)])
-> [WithVisibility (AnyCategory SourceContext)]
-> m [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> a -> b
$ (WithVisibility (AnyCategory SourceContext)
 -> WithVisibility (AnyCategory SourceContext))
-> [WithVisibility (AnyCategory SourceContext)]
-> [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> [a] -> [b]
map ((Set CodeVisibility -> Set CodeVisibility)
-> WithVisibility (AnyCategory SourceContext)
-> WithVisibility (AnyCategory SourceContext)
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 SourceContext)]
cs'
    loadAllPublic :: (Namespace, Namespace)
-> [(FilePath, [FilePath])]
-> m ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
loadAllPublic (Namespace
ns2,Namespace
ns3) [(FilePath, [FilePath])]
fs2 = do
      [(FilePath, FilePath)]
fs2' <- ([[(FilePath, FilePath)]] -> [(FilePath, FilePath)])
-> m [[(FilePath, FilePath)]] -> m [(FilePath, FilePath)]
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[(FilePath, FilePath)]] -> [(FilePath, FilePath)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (m [[(FilePath, FilePath)]] -> m [(FilePath, FilePath)])
-> m [[(FilePath, FilePath)]] -> m [(FilePath, FilePath)]
forall a b. (a -> b) -> a -> b
$ ((FilePath, [FilePath]) -> m [(FilePath, FilePath)])
-> [(FilePath, [FilePath])] -> m [[(FilePath, FilePath)]]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM ((FilePath -> [FilePath] -> m [(FilePath, FilePath)])
-> (FilePath, [FilePath]) -> m [(FilePath, FilePath)]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry ((FilePath -> [FilePath] -> m [(FilePath, FilePath)])
 -> (FilePath, [FilePath]) -> m [(FilePath, FilePath)])
-> (FilePath -> [FilePath] -> m [(FilePath, FilePath)])
-> (FilePath, [FilePath])
-> m [(FilePath, FilePath)]
forall a b. (a -> b) -> a -> b
$ r -> FilePath -> [FilePath] -> m [(FilePath, FilePath)]
forall r (m :: * -> *).
(PathIOHandler r, MonadIO m, CollectErrorsM m) =>
r -> FilePath -> [FilePath] -> m [(FilePath, FilePath)]
forall (m :: * -> *).
(MonadIO m, CollectErrorsM m) =>
r -> FilePath -> [FilePath] -> m [(FilePath, FilePath)]
zipWithContents r
r) [(FilePath, [FilePath])]
fs2
      [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
loaded <- ((FilePath, FilePath)
 -> m ([WithVisibility (AnyCategory SourceContext)], [FilePath]))
-> [(FilePath, FilePath)]
-> m [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
forall (m :: * -> *) a b.
CollectErrorsM m =>
(a -> m b) -> [a] -> m [b]
mapCompilerM (FilePath, FilePath)
-> m ([WithVisibility (AnyCategory SourceContext)], [FilePath])
forall {m :: * -> *}.
(ErrorContextM m, MonadIO m) =>
(FilePath, FilePath)
-> m ([WithVisibility (AnyCategory SourceContext)], [FilePath])
loadPublic [(FilePath, FilePath)]
fs2'
      ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
-> m ([WithVisibility (AnyCategory SourceContext)], Set FilePath)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([[WithVisibility (AnyCategory SourceContext)]]
-> [WithVisibility (AnyCategory SourceContext)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[WithVisibility (AnyCategory SourceContext)]]
 -> [WithVisibility (AnyCategory SourceContext)])
-> [[WithVisibility (AnyCategory SourceContext)]]
-> [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> a -> b
$ (([WithVisibility (AnyCategory SourceContext)], [FilePath])
 -> [WithVisibility (AnyCategory SourceContext)])
-> [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
-> [[WithVisibility (AnyCategory SourceContext)]]
forall a b. (a -> b) -> [a] -> [b]
map ([WithVisibility (AnyCategory SourceContext)], [FilePath])
-> [WithVisibility (AnyCategory SourceContext)]
forall a b. (a, b) -> a
fst [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
loaded,[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
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[FilePath]] -> [FilePath]) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ (([WithVisibility (AnyCategory SourceContext)], [FilePath])
 -> [FilePath])
-> [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
-> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map ([WithVisibility (AnyCategory SourceContext)], [FilePath])
-> [FilePath]
forall a b. (a, b) -> b
snd [([WithVisibility (AnyCategory SourceContext)], [FilePath])]
loaded)
      where
        loadPublic :: (FilePath, FilePath)
-> m ([WithVisibility (AnyCategory SourceContext)], [FilePath])
loadPublic (FilePath, FilePath)
p3 = do
          ([PragmaSource SourceContext]
pragmas,[AnyCategory SourceContext]
cs) <- (FilePath, FilePath)
-> m ([PragmaSource SourceContext], [AnyCategory SourceContext])
forall (m :: * -> *).
ErrorContextM m =>
(FilePath, FilePath)
-> m ([PragmaSource SourceContext], [AnyCategory SourceContext])
parsePublicSource (FilePath, FilePath)
p3
          [FilePath]
xs <- if (PragmaSource SourceContext -> Bool)
-> [PragmaSource SourceContext] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any PragmaSource SourceContext -> Bool
forall c. PragmaSource c -> Bool
isModuleOnly [PragmaSource SourceContext]
pragmas
                   then IO [FilePath] -> m [FilePath]
forall (m :: * -> *) a. (MonadIO m, ErrorContextM m) => IO a -> m a
errorFromIO (IO [FilePath] -> m [FilePath]) -> IO [FilePath] -> m [FilePath]
forall a b. (a -> b) -> a -> b
$ (FilePath -> [FilePath]) -> IO FilePath -> IO [FilePath]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
:[]) (IO FilePath -> IO [FilePath]) -> IO FilePath -> IO [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
canonicalizePath (FilePath -> IO FilePath) -> FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath
p FilePath -> FilePath -> FilePath
</> (FilePath, FilePath) -> FilePath
forall a b. (a, b) -> a
fst (FilePath, FilePath)
p3
                   else [FilePath] -> m [FilePath]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
          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 (PragmaSource SourceContext -> Bool)
-> [PragmaSource SourceContext] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any PragmaSource SourceContext -> Bool
forall c. PragmaSource c -> Bool
isTestsOnly  [PragmaSource SourceContext]
pragmas then [CodeVisibility
TestsOnly]  else []) [CodeVisibility] -> [CodeVisibility] -> [CodeVisibility]
forall a. [a] -> [a] -> [a]
++
                     (if (PragmaSource SourceContext -> Bool)
-> [PragmaSource SourceContext] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any PragmaSource SourceContext -> Bool
forall c. PragmaSource c -> Bool
isModuleOnly [PragmaSource SourceContext]
pragmas then [CodeVisibility
ModuleOnly] else [])
          let cs' :: [AnyCategory SourceContext]
cs' = if (PragmaSource SourceContext -> Bool)
-> [PragmaSource SourceContext] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any PragmaSource SourceContext -> Bool
forall c. PragmaSource c -> Bool
isModuleOnly [PragmaSource SourceContext]
pragmas
                       then (AnyCategory SourceContext -> AnyCategory SourceContext)
-> [AnyCategory SourceContext] -> [AnyCategory SourceContext]
forall a b. (a -> b) -> [a] -> [b]
map (Namespace -> AnyCategory SourceContext -> AnyCategory SourceContext
forall c. Namespace -> AnyCategory c -> AnyCategory c
setCategoryNamespace Namespace
ns3) [AnyCategory SourceContext]
cs
                       else (AnyCategory SourceContext -> AnyCategory SourceContext)
-> [AnyCategory SourceContext] -> [AnyCategory SourceContext]
forall a b. (a -> b) -> [a] -> [b]
map (Namespace -> AnyCategory SourceContext -> AnyCategory SourceContext
forall c. Namespace -> AnyCategory c -> AnyCategory c
setCategoryNamespace Namespace
ns2) [AnyCategory SourceContext]
cs
          ([WithVisibility (AnyCategory SourceContext)], [FilePath])
-> m ([WithVisibility (AnyCategory SourceContext)], [FilePath])
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((AnyCategory SourceContext
 -> WithVisibility (AnyCategory SourceContext))
-> [AnyCategory SourceContext]
-> [WithVisibility (AnyCategory SourceContext)]
forall a b. (a -> b) -> [a] -> [b]
map (Set CodeVisibility
-> AnyCategory SourceContext
-> WithVisibility (AnyCategory SourceContext)
forall a. Set CodeVisibility -> a -> WithVisibility a
WithVisibility Set CodeVisibility
tags) [AnyCategory SourceContext]
cs',[FilePath]
xs)