{-
   Copyright 2016, Dominic Orchard, Andrew Rice, Mistral Contrastin, Matthew Danish

   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.
-}

{- This module collects together stubs that connect analysis/transformations
   with the input -> output procedures -}

{-# LANGUAGE DoAndIfThenElse      #-}
{-# LANGUAGE FlexibleInstances    #-}
{-# LANGUAGE OverloadedStrings    #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{-# LANGUAGE TupleSections        #-}
{-# LANGUAGE TypeSynonymInstances #-}

module Camfort.Functionality
  (
  -- * Datatypes
    AnnotationType(..)
  , CamfortEnv(..)
  -- * Commands
  , ast
  , countVarDecls
  , implicitNone
  , allocCheck
  , fpCheck
  , useCheck
  , arrayCheck
  -- ** Stencil Analysis
  , stencilsCheck
  , stencilsInfer
  , stencilsSynth
  -- ** Unit Analysis
  , unitsCriticals
  , unitsCheck
  , unitsDump
  , unitsInfer
  , unitsCompile
  , unitsSynth
  -- ** Invariants Analysis
  , invariantsCheck
  -- ** Refactorings
  , common
  , dead
  , equivalences
  , ddtRefactor
  , ddtInfer
  , ddtCheck
  , ddtSynth
  , ddtCompile
  -- ** Project Management
  , camfortInitialize
  ) where

import           Camfort.Analysis
import           Camfort.Analysis.Logger
import           Camfort.Analysis.ModFile (readParseSrcFile,  MFCompiler, getModFiles, genModFiles
                                          , readParseSrcDir, readParseSrcDirP, simpleCompiler)
import           Camfort.Analysis.Simple
import           Camfort.Helpers (FileOrDir, Filename)
import           Camfort.Input
import qualified Camfort.Specification.DerivedDataType as DDT
import qualified Camfort.Specification.Hoare as Hoare
import qualified Camfort.Specification.Stencils as Stencils
import           Camfort.Specification.Stencils.Analysis (compileStencils)
import qualified Camfort.Specification.Units as LU
import           Camfort.Specification.Units.Analysis (compileUnits)
import           Camfort.Specification.Units.Analysis.Consistent (checkUnits)
import           Camfort.Specification.Units.Analysis.Criticals (inferCriticalVariables)
import           Camfort.Specification.Units.Analysis.Infer (InferenceResult(..), InferenceReport(..), inferUnits)
import           Camfort.Specification.Units.Annotation (unitInfo)
import           Camfort.Specification.Units.ModFile (dumpModFileCompiledUnits)
import           Camfort.Specification.Units.Monad (runUnitAnalysis, unitOpts0)
import           Camfort.Specification.Units.MonadTypes (LiteralsOpt, UnitAnalysis, UnitEnv (..), UnitOpts (..))
import           Camfort.Transformation.CommonBlockElim
import           Camfort.Transformation.DeadCode
import           Camfort.Transformation.EquivalenceElim
import           Control.DeepSeq
import           Control.Monad
import           Control.Monad.IO.Class
import qualified Data.ByteString.Lazy as LB
import           Data.Char (toLower)
import           Data.List (intersperse)
import           Data.Maybe (fromMaybe)
import qualified Language.Fortran.Analysis as FA
import qualified Language.Fortran.Analysis.ModGraph as FM
import qualified Language.Fortran.Analysis.Renaming as FA
import           Language.Fortran.Version (FortranVersion(..))
import qualified Language.Fortran.Util.ModFile as FM
import           Pipes
import qualified Pipes.Prelude as P
import           Prelude hiding (mod)
import           System.Directory
import           System.Directory (doesDirectoryExist, createDirectoryIfMissing, getCurrentDirectory)
import           System.FilePath (takeDirectory, (</>), takeExtension, replaceExtension)
import           System.IO
import           Text.PrettyPrint.GenericPretty (pp)

data AnnotationType = ATDefault | Doxygen | Ford


-- | Retrieve the marker character compatible with the given
-- type of annotation.
markerChar :: AnnotationType -> Char
markerChar :: AnnotationType -> Char
markerChar AnnotationType
Doxygen   = Char
'<'
markerChar AnnotationType
Ford      = Char
'!'
markerChar AnnotationType
ATDefault = Char
'='

data CamfortEnv =
  CamfortEnv
  { CamfortEnv -> [Char]
ceInputSources   :: FileOrDir
  , CamfortEnv -> Maybe [Char]
ceIncludeDir     :: Maybe FileOrDir
  , CamfortEnv -> [[Char]]
ceExcludeFiles   :: [Filename]
  , CamfortEnv -> LogLevel
ceLogLevel       :: LogLevel
  , CamfortEnv -> Bool
ceSourceSnippets :: Bool
  , CamfortEnv -> Maybe FortranVersion
ceFortranVersion :: Maybe FortranVersion
  }

--------------------------------------------------------------------------------
-- *  Running Functionality

runWithOutput
  :: (Describe e, Describe w)
  => String
  -- ^ Functionality desription
  -> AnalysisProgram e w IO a b
  -- ^ Analysis program
  -> (FileOrDir -> FilePath -> AnalysisRunner e w IO a b r)
  -- ^ Analysis runner
  -> MFCompiler i IO
  -- ^ Mod file compiler
  -> i
  -- ^ Mod file input
  -> FilePath
  -> CamfortEnv
  -> IO r
runWithOutput :: forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput [Char]
description AnalysisProgram e w IO a b
program [Char] -> [Char] -> AnalysisRunner e w IO a b r
runner MFCompiler i IO
mfCompiler i
mfInput [Char]
outSrc CamfortEnv
env =
  let runner' :: AnalysisRunner e w IO a b r
runner' = [Char] -> [Char] -> AnalysisRunner e w IO a b r
runner (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) [Char]
outSrc
  in [Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunner e w IO a b r
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO r
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunner e w IO a b r
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO r
runFunctionality [Char]
description AnalysisProgram e w IO a b
program AnalysisRunner e w IO a b r
runner' MFCompiler i IO
mfCompiler i
mfInput CamfortEnv
env


runFunctionality
  :: (Describe e, Describe w)
  => String
  -- ^ Functionality desription
  -> AnalysisProgram e w IO a b
  -- ^ Analysis program
  -> AnalysisRunner e w IO a b r
  -- ^ Analysis runner
  -> MFCompiler i IO
  -- ^ Mod file compiler
  -> i
  -- ^ Mod file input
  -> CamfortEnv
  -> IO r
runFunctionality :: forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunner e w IO a b r
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO r
runFunctionality [Char]
description AnalysisProgram e w IO a b
program AnalysisRunner e w IO a b r
runner MFCompiler i IO
_ i
_ CamfortEnv
env = do
  [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
description [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" '" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ CamfortEnv -> [Char]
ceInputSources CamfortEnv
env [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
  [Char]
incDir' <- IO [Char] -> ([Char] -> IO [Char]) -> Maybe [Char] -> IO [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO [Char]
getCurrentDirectory [Char] -> IO [Char]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CamfortEnv -> Maybe [Char]
ceIncludeDir CamfortEnv
env)
  Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
incDir'
  let incDir :: [Char]
incDir | Bool
isDir     = [Char]
incDir'
             | Bool
otherwise = [Char] -> [Char]
takeDirectory [Char]
incDir'
  -- Previously...
--modFiles <- genModFiles mfCompiler mfInput incDir (ceExcludeFiles env)
  -- ...instead for now, just get the mod files

  ModFiles
modFiles <- [Char] -> IO ModFiles
getModFiles [Char]
incDir
  [(ProgramFile A, SourceText)]
pfsTexts <- Maybe FortranVersion
-> ModFiles
-> [Char]
-> [[Char]]
-> IO [(ProgramFile A, SourceText)]
readParseSrcDir (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) ModFiles
modFiles (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) (CamfortEnv -> [[Char]]
ceExcludeFiles CamfortEnv
env)
  AnalysisRunner e w IO a b r
runner AnalysisProgram e w IO a b
program (Bool -> LogOutput IO
forall (m :: * -> *). MonadIO m => Bool -> LogOutput m
logOutputStd Bool
True) (CamfortEnv -> LogLevel
ceLogLevel CamfortEnv
env) (CamfortEnv -> Bool
ceSourceSnippets CamfortEnv
env) ModFiles
modFiles [(ProgramFile A, SourceText)]
pfsTexts

runFunctionalityP
  :: (Describe e, Describe w, ExitCodeOfReport b)
  => String
  -- ^ Functionality desription
  -> AnalysisProgram e w IO a b
  -- ^ Analysis program
  -> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
  -- ^ Analysis runner
  -> MFCompiler i IO
  -- ^ Mod file compiler
  -> i
  -- ^ Mod file input
  -> CamfortEnv
  -> IO Int
runFunctionalityP :: forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP [Char]
description AnalysisProgram e w IO a b
program AnalysisRunnerP e w IO a b (AnalysisReport e w b)
runner MFCompiler i IO
_ i
_ CamfortEnv
env = do
  [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
description [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" '" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ CamfortEnv -> [Char]
ceInputSources CamfortEnv
env [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
  [Char]
incDir' <- IO [Char] -> ([Char] -> IO [Char]) -> Maybe [Char] -> IO [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO [Char]
getCurrentDirectory [Char] -> IO [Char]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CamfortEnv -> Maybe [Char]
ceIncludeDir CamfortEnv
env)
  Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
incDir'
  let incDir :: [Char]
incDir | Bool
isDir     = [Char]
incDir'
             | Bool
otherwise = [Char] -> [Char]
takeDirectory [Char]
incDir'
  -- Previously...
--modFiles <- genModFiles mfCompiler mfInput incDir (ceExcludeFiles env)
  -- ...instead for now, just get the mod files

  ModFiles
modFiles <- [Char] -> IO ModFiles
getModFiles [Char]
incDir

  [AnalysisReport e w b]
reports <- Producer (AnalysisReport e w b) IO () -> IO [AnalysisReport e w b]
forall (m :: * -> *) a. Monad m => Producer a m () -> m [a]
P.toListM (Producer (AnalysisReport e w b) IO ()
 -> IO [AnalysisReport e w b])
-> Producer (AnalysisReport e w b) IO ()
-> IO [AnalysisReport e w b]
forall a b. (a -> b) -> a -> b
$
    Maybe FortranVersion
-> ModFiles
-> [Char]
-> [[Char]]
-> Producer' (ProgramFile A, SourceText) IO ()
forall (m :: * -> *).
MonadIO m =>
Maybe FortranVersion
-> ModFiles
-> [Char]
-> [[Char]]
-> Producer' (ProgramFile A, SourceText) m ()
readParseSrcDirP (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) ModFiles
modFiles (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) (CamfortEnv -> [[Char]]
ceExcludeFiles CamfortEnv
env) Proxy Void () () (ProgramFile A, SourceText) IO ()
-> Proxy
     () (ProgramFile A, SourceText) () (AnalysisReport e w b) IO ()
-> Producer (AnalysisReport e w b) IO ()
forall (m :: * -> *) a' a b r c' c.
Functor m =>
Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
>->
    AnalysisRunnerP e w IO a b (AnalysisReport e w b)
runner AnalysisProgram e w IO a b
program (Bool -> LogOutput IO
forall (m :: * -> *). MonadIO m => Bool -> LogOutput m
logOutputStd Bool
True) (CamfortEnv -> LogLevel
ceLogLevel CamfortEnv
env) (CamfortEnv -> Bool
ceSourceSnippets CamfortEnv
env) ModFiles
modFiles
  Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Int -> IO Int)
-> ([AnalysisReport e w b] -> Int)
-> [AnalysisReport e w b]
-> IO Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [AnalysisReport e w b] -> Int
forall a. ExitCodeOfReport a => [a] -> Int
exitCodeOfSet ([AnalysisReport e w b] -> IO Int)
-> [AnalysisReport e w b] -> IO Int
forall a b. (a -> b) -> a -> b
$ [AnalysisReport e w b]
reports

--------------------------------------------------------------------------------
-- * Wrappers on all of the features

ast :: CamfortEnv -> IO ()
ast :: CamfortEnv -> IO ()
ast CamfortEnv
env = do
    [Char]
incDir' <- IO [Char] -> ([Char] -> IO [Char]) -> Maybe [Char] -> IO [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO [Char]
getCurrentDirectory [Char] -> IO [Char]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CamfortEnv -> Maybe [Char]
ceIncludeDir CamfortEnv
env)
    ModFiles
modFiles <- [Char] -> IO ModFiles
getModFiles [Char]
incDir'
    [(ProgramFile A, SourceText)]
xs <- Maybe FortranVersion
-> ModFiles
-> [Char]
-> [[Char]]
-> IO [(ProgramFile A, SourceText)]
readParseSrcDir (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) ModFiles
modFiles (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) (CamfortEnv -> [[Char]]
ceExcludeFiles CamfortEnv
env)
    [ProgramFile A] -> IO ()
forall a. Show a => a -> IO ()
print ([ProgramFile A] -> IO ())
-> ([(ProgramFile A, SourceText)] -> [ProgramFile A])
-> [(ProgramFile A, SourceText)]
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ProgramFile A, SourceText) -> ProgramFile A)
-> [(ProgramFile A, SourceText)] -> [ProgramFile A]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ProgramFile A, SourceText) -> ProgramFile A
forall a b. (a, b) -> a
fst ([(ProgramFile A, SourceText)] -> IO ())
-> [(ProgramFile A, SourceText)] -> IO ()
forall a b. (a -> b) -> a -> b
$ [(ProgramFile A, SourceText)]
xs


countVarDecls :: CamfortEnv -> IO Int
countVarDecls :: CamfortEnv -> IO Int
countVarDecls =
  [Char]
-> AnalysisProgram () () IO (ProgramFile A) VarCountReport
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     VarCountReport
     (AnalysisReport () () VarCountReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Counting variable declarations in"
  (PureAnalysis () () VarCountReport
-> AnalysisT () () IO VarCountReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis () () VarCountReport
 -> AnalysisT () () IO VarCountReport)
-> (ProgramFile A -> PureAnalysis () () VarCountReport)
-> AnalysisProgram () () IO (ProgramFile A) VarCountReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis () () VarCountReport
forall a.
Data a =>
ProgramFile a -> PureAnalysis () () VarCountReport
countVariableDeclarations)
  (Text
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     VarCountReport
     (AnalysisReport () () VarCountReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"count variable declarations")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

dead :: FileOrDir -> CamfortEnv -> IO Int
dead :: [Char] -> CamfortEnv -> IO Int
dead =
  [Char]
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         Void
         Void
         IO
         [ProgramFile A]
         ((), [Either Void (ProgramFile A)])
         Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
  [Char]
"Eliminating dead code in"
  ((PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
 -> AnalysisT Void Void IO ((), [Either Void (ProgramFile A)]))
-> ([ProgramFile A]
    -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall a b.
(a -> b) -> ([ProgramFile A] -> a) -> [ProgramFile A] -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
-> AnalysisT Void Void IO ((), [Either Void (ProgramFile A)])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (([ProgramFile A]
  -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
 -> AnalysisProgram
      Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)]))
-> ((ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
    -> [ProgramFile A]
    -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
-> (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> [ProgramFile A]
-> PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
forall (m :: * -> *) e w.
Monad m =>
AnalysisProgram e w m (ProgramFile A) (ProgramFile A)
-> AnalysisProgram
     e w m [ProgramFile A] ((), [Either e (ProgramFile A)])
perFileRefactoring ((ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
 -> AnalysisProgram
      Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)]))
-> (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall a b. (a -> b) -> a -> b
$ Bool -> ProgramFile A -> DeadCodeAnalysis (ProgramFile A)
deadCode Bool
False)
  (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     Void
     Void
     IO
     [ProgramFile A]
     ((), [Either Void (ProgramFile A)])
     Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"dead code elimination")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()


common :: FileOrDir -> CamfortEnv -> IO Int
common :: [Char] -> CamfortEnv -> IO Int
common [Char]
outSrc =
  [Char]
-> AnalysisProgram
     Void Void IO [ProgramFile A] ([ProgramFile A], [ProgramFile A])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         Void
         Void
         IO
         [ProgramFile A]
         ([ProgramFile A], [ProgramFile A])
         Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
  [Char]
"Refactoring common blocks in"
  (PureAnalysis Void Void ([ProgramFile A], [ProgramFile A])
-> AnalysisT Void Void IO ([ProgramFile A], [ProgramFile A])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis Void Void ([ProgramFile A], [ProgramFile A])
 -> AnalysisT Void Void IO ([ProgramFile A], [ProgramFile A]))
-> ([ProgramFile A]
    -> PureAnalysis Void Void ([ProgramFile A], [ProgramFile A]))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ([ProgramFile A], [ProgramFile A])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char]
-> [ProgramFile A]
-> PureAnalysis Void Void ([ProgramFile A], [ProgramFile A])
commonElimToModules ([Char] -> [Char]
takeDirectory [Char]
outSrc [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"/"))
  (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     Void Void IO [ProgramFile A] ([ProgramFile A], [ProgramFile A]) Int
forall e w.
(Describe e, Describe w) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] ([ProgramFile A], [ProgramFile A]) Int
doRefactorAndCreate Text
"common block refactoring")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()
  [Char]
outSrc


equivalences :: FileOrDir -> CamfortEnv -> IO Int
equivalences :: [Char] -> CamfortEnv -> IO Int
equivalences =
  [Char]
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         Void
         Void
         IO
         [ProgramFile A]
         ((), [Either Void (ProgramFile A)])
         Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
  [Char]
"Refactoring equivalences blocks in"
  ((PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
 -> AnalysisT Void Void IO ((), [Either Void (ProgramFile A)]))
-> ([ProgramFile A]
    -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall a b.
(a -> b) -> ([ProgramFile A] -> a) -> [ProgramFile A] -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
-> AnalysisT Void Void IO ((), [Either Void (ProgramFile A)])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (([ProgramFile A]
  -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
 -> AnalysisProgram
      Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)]))
-> ((ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
    -> [ProgramFile A]
    -> PureAnalysis Void Void ((), [Either Void (ProgramFile A)]))
-> (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> [ProgramFile A]
-> PureAnalysis Void Void ((), [Either Void (ProgramFile A)])
forall (m :: * -> *) e w.
Monad m =>
AnalysisProgram e w m (ProgramFile A) (ProgramFile A)
-> AnalysisProgram
     e w m [ProgramFile A] ((), [Either e (ProgramFile A)])
perFileRefactoring ((ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
 -> AnalysisProgram
      Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)]))
-> (ProgramFile A -> DeadCodeAnalysis (ProgramFile A))
-> AnalysisProgram
     Void Void IO [ProgramFile A] ((), [Either Void (ProgramFile A)])
forall a b. (a -> b) -> a -> b
$ ProgramFile A -> DeadCodeAnalysis (ProgramFile A)
refactorEquivalences)
  (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     Void
     Void
     IO
     [ProgramFile A]
     ((), [Either Void (ProgramFile A)])
     Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"equivalence block refactoring")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

implicitNone :: Bool -> CamfortEnv -> IO Int
implicitNone :: Bool -> CamfortEnv -> IO Int
implicitNone Bool
allPU =
  [Char]
-> AnalysisProgram [Char] () IO (ProgramFile A) ImplicitNoneReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     ImplicitNoneReport
     (AnalysisReport [Char] () ImplicitNoneReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking 'implicit none' completeness"
  (PureAnalysis [Char] () ImplicitNoneReport
-> AnalysisT [Char] () IO ImplicitNoneReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () ImplicitNoneReport
 -> AnalysisT [Char] () IO ImplicitNoneReport)
-> (ProgramFile A -> PureAnalysis [Char] () ImplicitNoneReport)
-> AnalysisProgram [Char] () IO (ProgramFile A) ImplicitNoneReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Bool -> ProgramFile A -> PureAnalysis [Char] () ImplicitNoneReport
forall a.
Data a =>
Bool -> ProgramFile a -> PureAnalysis [Char] () ImplicitNoneReport
checkImplicitNone Bool
allPU))
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     ImplicitNoneReport
     (AnalysisReport [Char] () ImplicitNoneReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check 'implicit none'")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

allocCheck :: CamfortEnv -> IO Int
allocCheck :: CamfortEnv -> IO Int
allocCheck =
  [Char]
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckAllocReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckAllocReport
     (AnalysisReport [Char] () CheckAllocReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking allocate / deallocate usage"
  (PureAnalysis [Char] () CheckAllocReport
-> AnalysisT [Char] () IO CheckAllocReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () CheckAllocReport
 -> AnalysisT [Char] () IO CheckAllocReport)
-> (ProgramFile A -> PureAnalysis [Char] () CheckAllocReport)
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckAllocReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () CheckAllocReport
forall a.
Data a =>
ProgramFile a -> PureAnalysis [Char] () CheckAllocReport
checkAllocateStatements)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckAllocReport
     (AnalysisReport [Char] () CheckAllocReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check allocate / deallocate")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

fpCheck :: CamfortEnv -> IO Int
fpCheck :: CamfortEnv -> IO Int
fpCheck =
  [Char]
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckFPReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckFPReport
     (AnalysisReport [Char] () CheckFPReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking usage of floating point"
  (PureAnalysis [Char] () CheckFPReport
-> AnalysisT [Char] () IO CheckFPReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () CheckFPReport
 -> AnalysisT [Char] () IO CheckFPReport)
-> (ProgramFile A -> PureAnalysis [Char] () CheckFPReport)
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckFPReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () CheckFPReport
forall a.
Data a =>
ProgramFile a -> PureAnalysis [Char] () CheckFPReport
checkFloatingPointUse)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckFPReport
     (AnalysisReport [Char] () CheckFPReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check floating point")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

useCheck :: CamfortEnv -> IO Int
useCheck :: CamfortEnv -> IO Int
useCheck =
  [Char]
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckUseReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckUseReport
     (AnalysisReport [Char] () CheckUseReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking usage of USE statements"
  (PureAnalysis [Char] () CheckUseReport
-> AnalysisT [Char] () IO CheckUseReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () CheckUseReport
 -> AnalysisT [Char] () IO CheckUseReport)
-> (ProgramFile A -> PureAnalysis [Char] () CheckUseReport)
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckUseReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () CheckUseReport
forall a.
Data a =>
ProgramFile a -> PureAnalysis [Char] () CheckUseReport
checkModuleUse)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckUseReport
     (AnalysisReport [Char] () CheckUseReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check module USE")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

arrayCheck :: CamfortEnv -> IO Int
arrayCheck :: CamfortEnv -> IO Int
arrayCheck =
  [Char]
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckArrayReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckArrayReport
     (AnalysisReport [Char] () CheckArrayReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking array usage"
  (PureAnalysis [Char] () CheckArrayReport
-> AnalysisT [Char] () IO CheckArrayReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () CheckArrayReport
 -> AnalysisT [Char] () IO CheckArrayReport)
-> (ProgramFile A -> PureAnalysis [Char] () CheckArrayReport)
-> AnalysisProgram [Char] () IO (ProgramFile A) CheckArrayReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () CheckArrayReport
forall a.
Data a =>
ProgramFile a -> PureAnalysis [Char] () CheckArrayReport
checkArrayUse)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     CheckArrayReport
     (AnalysisReport [Char] () CheckArrayReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check array usage")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

ddtRefactor :: FileOrDir -> CamfortEnv -> IO Int
ddtRefactor :: [Char] -> CamfortEnv -> IO Int
ddtRefactor =
  [Char]
-> AnalysisProgram
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         [Char]
         ()
         IO
         [ProgramFile A]
         (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
         Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
  [Char]
"Refactoring derived datatypes"
  (PureAnalysis
  [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
-> AnalysisT
     [Char]
     ()
     IO
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis
   [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
 -> AnalysisT
      [Char]
      ()
      IO
      (DerivedDataTypeReport, [Either [Char] (ProgramFile A)]))
-> ([ProgramFile A]
    -> PureAnalysis
         [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)]))
-> AnalysisProgram
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ProgramFile A]
-> PureAnalysis
     [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
DDT.refactor)
  (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
     Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"infer derived data types")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

ddtSynth :: AnnotationType -> FileOrDir -> CamfortEnv -> IO Int
ddtSynth :: AnnotationType -> [Char] -> CamfortEnv -> IO Int
ddtSynth AnnotationType
annType =
  [Char]
-> AnalysisProgram
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         [Char]
         ()
         IO
         [ProgramFile A]
         (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
         Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
  [Char]
"Synthesising derived datatypes"
  (PureAnalysis
  [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
-> AnalysisT
     [Char]
     ()
     IO
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis
   [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
 -> AnalysisT
      [Char]
      ()
      IO
      (DerivedDataTypeReport, [Either [Char] (ProgramFile A)]))
-> ([ProgramFile A]
    -> PureAnalysis
         [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)]))
-> AnalysisProgram
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char
-> [ProgramFile A]
-> PureAnalysis
     [Char] () (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
DDT.synth (AnnotationType -> Char
markerChar AnnotationType
annType))
  (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     [Char]
     ()
     IO
     [ProgramFile A]
     (DerivedDataTypeReport, [Either [Char] (ProgramFile A)])
     Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"synth derived data types")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

ddtCheck :: CamfortEnv -> IO Int
ddtCheck :: CamfortEnv -> IO Int
ddtCheck =
  [Char]
-> AnalysisProgram
     [Char] () IO (ProgramFile A) DerivedDataTypeReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     DerivedDataTypeReport
     (AnalysisReport [Char] () DerivedDataTypeReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking derived datatype annotations"
  (PureAnalysis [Char] () DerivedDataTypeReport
-> AnalysisT [Char] () IO DerivedDataTypeReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () DerivedDataTypeReport
 -> AnalysisT [Char] () IO DerivedDataTypeReport)
-> (ProgramFile A -> PureAnalysis [Char] () DerivedDataTypeReport)
-> AnalysisProgram
     [Char] () IO (ProgramFile A) DerivedDataTypeReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () DerivedDataTypeReport
DDT.check)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     DerivedDataTypeReport
     (AnalysisReport [Char] () DerivedDataTypeReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"check derived datatypes")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

ddtInfer :: CamfortEnv -> IO Int
ddtInfer :: CamfortEnv -> IO Int
ddtInfer =
  [Char]
-> AnalysisProgram
     [Char] () IO (ProgramFile A) DerivedDataTypeReport
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     DerivedDataTypeReport
     (AnalysisReport [Char] () DerivedDataTypeReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Inferring derived datatypes"
  (PureAnalysis [Char] () DerivedDataTypeReport
-> AnalysisT [Char] () IO DerivedDataTypeReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis [Char] () DerivedDataTypeReport
 -> AnalysisT [Char] () IO DerivedDataTypeReport)
-> (ProgramFile A -> PureAnalysis [Char] () DerivedDataTypeReport)
-> AnalysisProgram
     [Char] () IO (ProgramFile A) DerivedDataTypeReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis [Char] () DerivedDataTypeReport
DDT.infer)
  (Text
-> AnalysisRunnerP
     [Char]
     ()
     IO
     (ProgramFile A)
     DerivedDataTypeReport
     (AnalysisReport [Char] () DerivedDataTypeReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"infer derived datatypes")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()

ddtCompile :: CamfortEnv -> IO Int
ddtCompile :: CamfortEnv -> IO Int
ddtCompile CamfortEnv
env = do
  let description :: [Char]
description = [Char]
"Compiling derived datatypes for"
  [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
description [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" '" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ CamfortEnv -> [Char]
ceInputSources CamfortEnv
env [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
  [Char]
incDir' <- IO [Char] -> ([Char] -> IO [Char]) -> Maybe [Char] -> IO [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO [Char]
getCurrentDirectory [Char] -> IO [Char]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CamfortEnv -> Maybe [Char]
ceIncludeDir CamfortEnv
env)
  Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
incDir'
  let incDir :: [Char]
incDir | Bool
isDir     = [Char]
incDir'
             | Bool
otherwise = [Char] -> [Char]
takeDirectory [Char]
incDir'
  ModFiles
modFileNames <- [Char] -> IO ModFiles
getModFiles [Char]
incDir

  -- Run the gen mod file routine directly on the input source
  ModFiles
modFiles <- Maybe FortranVersion
-> ModFiles
-> MFCompiler () IO
-> ()
-> [Char]
-> [[Char]]
-> IO ModFiles
forall (m :: * -> *) r.
MonadIO m =>
Maybe FortranVersion
-> ModFiles
-> MFCompiler r m
-> r
-> [Char]
-> [[Char]]
-> m ModFiles
genModFiles (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) ModFiles
modFileNames MFCompiler () IO
DDT.compile () (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) (CamfortEnv -> [[Char]]
ceExcludeFiles CamfortEnv
env)
  -- Write the mod files out
  ModFiles -> (ModFile -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ModFiles
modFiles ((ModFile -> IO ()) -> IO ()) -> (ModFile -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ ModFile
modFile -> do
     let mfname :: [Char]
mfname = [Char] -> [Char] -> [Char]
replaceExtension (ModFile -> [Char]
FM.moduleFilename ModFile
modFile) [Char]
FM.modFileSuffix
     [Char] -> ByteString -> IO ()
LB.writeFile [Char]
mfname (ModFiles -> ByteString
FM.encodeModFile [ModFile
modFile])
  Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Int
0

{- Units feature -}

runUnitsFunctionalityP
  :: (Describe e, Describe w, ExitCodeOfReport b)
  => String
  -> (UnitOpts -> AnalysisProgram e w IO a b)
  -> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
  -> LiteralsOpt
  -> CamfortEnv
  -> IO Int
runUnitsFunctionalityP :: forall e w b a.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> (UnitOpts -> AnalysisProgram e w IO a b)
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
runUnitsFunctionalityP [Char]
description UnitOpts -> AnalysisProgram e w IO a b
unitsProgram AnalysisRunnerP e w IO a b (AnalysisReport e w b)
runner LiteralsOpt
opts =
  let uo :: UnitOpts
uo = LiteralsOpt -> UnitOpts
optsToUnitOpts LiteralsOpt
opts
  in [Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler UnitOpts IO
-> UnitOpts
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP [Char]
description (UnitOpts -> AnalysisProgram e w IO a b
unitsProgram UnitOpts
uo) AnalysisRunnerP e w IO a b (AnalysisReport e w b)
runner MFCompiler UnitOpts IO
compileUnits UnitOpts
uo

optsToUnitOpts :: LiteralsOpt -> UnitOpts
optsToUnitOpts :: LiteralsOpt -> UnitOpts
optsToUnitOpts LiteralsOpt
m = UnitOpts
o1
  where o1 :: UnitOpts
o1 = UnitOpts
unitOpts0 { uoLiterals :: LiteralsOpt
uoLiterals = LiteralsOpt
m
                       }

singlePfUnits
  :: UnitAnalysis a -> UnitOpts
  -> AnalysisProgram () () IO ProgramFile a
singlePfUnits :: forall a.
UnitAnalysis a
-> UnitOpts -> AnalysisProgram () () IO (ProgramFile A) a
singlePfUnits UnitAnalysis a
unitAnalysis UnitOpts
opts ProgramFile A
pf =
  let ue :: UnitEnv
ue = UnitEnv
        { unitOpts :: UnitOpts
unitOpts = UnitOpts
opts
        , unitProgramFile :: ProgramFile A
unitProgramFile = ProgramFile A
pf
        }
  in UnitEnv -> UnitAnalysis a -> AnalysisT () () IO a
forall a. UnitEnv -> UnitAnalysis a -> AnalysisT () () IO a
runUnitAnalysis UnitEnv
ue UnitAnalysis a
unitAnalysis


-- slight hack to make doRefactorAndCreate happy
-- singlePfUnits'
--   :: UnitAnalysis a -> UnitOpts
--   -> AnalysisProgram () () IO [ProgramFile] a
-- singlePfUnits' unitAnalysis opts (pf:_) =
--   let ue = UnitEnv
--         { unitOpts = opts
--         , unitProgramFile = pf
--         }
--   in runUnitAnalysis ue unitAnalysis
-- singlePfUnits' _ _ [] = error "singlePfUnits': no program file provided"

multiPfUnits
  :: (Describe a)
  => UnitAnalysis (Either e (a, b))
  -> UnitOpts
  -> AnalysisProgram () () IO [ProgramFile] (Text, [Either e b])
multiPfUnits :: forall a e b.
Describe a =>
UnitAnalysis (Either e (a, b))
-> UnitOpts
-> AnalysisProgram () () IO [ProgramFile A] (Text, [Either e b])
multiPfUnits UnitAnalysis (Either e (a, b))
unitAnalysis UnitOpts
opts [ProgramFile A]
pfs = do
  let ue :: ProgramFile A -> UnitEnv
ue ProgramFile A
pf = UnitEnv
        { unitOpts :: UnitOpts
unitOpts = UnitOpts
opts
        , unitProgramFile :: ProgramFile A
unitProgramFile = ProgramFile A
pf
        }

  [Either e (a, b)]
results <- (ProgramFile A -> AnalysisT () () IO (Either e (a, b)))
-> [ProgramFile A] -> AnalysisT () () IO [Either e (a, b)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (\ProgramFile A
pf -> UnitEnv
-> UnitAnalysis (Either e (a, b))
-> AnalysisT () () IO (Either e (a, b))
forall a. UnitEnv -> UnitAnalysis a -> AnalysisT () () IO a
runUnitAnalysis (ProgramFile A -> UnitEnv
ue ProgramFile A
pf) UnitAnalysis (Either e (a, b))
unitAnalysis) [ProgramFile A]
pfs
  let ([a]
rs, [Either e b]
ps) = (Either e (a, b) -> ([a], Either e b))
-> [Either e (a, b)] -> ([a], [Either e b])
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (((a, b) -> ([a], b)) -> Either e (a, b) -> ([a], Either e b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Either e a -> f (Either e b)
traverse (\(a
x, b
y) -> ([a
x], b
y))) [Either e (a, b)]
results

      rs' :: Text
rs' = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> ([a] -> [Text]) -> [a] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
intersperse Text
"\n" ([Text] -> [Text]) -> ([a] -> [Text]) -> [a] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map a -> Text
forall a. Describe a => a -> Text
describe ([a] -> Text) -> [a] -> Text
forall a b. (a -> b) -> a -> b
$ [a]
rs

  (Text, [Either e b]) -> AnalysisT () () IO (Text, [Either e b])
forall a. a -> AnalysisT () () IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text
rs', [Either e b]
ps)

unitsDump :: LiteralsOpt -> CamfortEnv -> IO Int
unitsDump :: LiteralsOpt -> CamfortEnv -> IO Int
unitsDump LiteralsOpt
_ CamfortEnv
env = do
  let modFileName :: [Char]
modFileName = CamfortEnv -> [Char]
ceInputSources CamfortEnv
env
  ByteString
modData <- [Char] -> IO ByteString
LB.readFile [Char]
modFileName
  let eResult :: Either [Char] ModFiles
eResult = ByteString -> Either [Char] ModFiles
FM.decodeModFile ByteString
modData
  case Either [Char] ModFiles
eResult of
    Left [Char]
msg -> do
      [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
modFileName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": Error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char] -> [Char]
forall a. Show a => a -> [Char]
show [Char]
msg
      Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
1
    Right ModFiles
modFiles -> do
      ModFiles -> (ModFile -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ ModFiles
modFiles ((ModFile -> IO ()) -> IO ()) -> (ModFile -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ ModFile
modFile -> do
        [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
modFileName [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": successfully parsed summary file."
        [Char] -> IO ()
putStrLn ([Char] -> IO ())
-> (Maybe [Char] -> [Char]) -> Maybe [Char] -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Maybe [Char] -> [Char]
forall a. a -> Maybe a -> a
fromMaybe [Char]
"unable to find units info" (Maybe [Char] -> IO ()) -> Maybe [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ ModFile -> Maybe [Char]
dumpModFileCompiledUnits ModFile
modFile
      Int -> IO Int
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
0

unitsCheck :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCheck :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCheck =
  [Char]
-> (UnitOpts
    -> AnalysisProgram () () IO (ProgramFile A) ConsistencyReport)
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     ConsistencyReport
     (AnalysisReport () () ConsistencyReport)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
forall e w b a.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> (UnitOpts -> AnalysisProgram e w IO a b)
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
runUnitsFunctionalityP
  [Char]
"Checking units for"
  (UnitAnalysis ConsistencyReport
-> UnitOpts
-> AnalysisProgram () () IO (ProgramFile A) ConsistencyReport
forall a.
UnitAnalysis a
-> UnitOpts -> AnalysisProgram () () IO (ProgramFile A) a
singlePfUnits UnitAnalysis ConsistencyReport
checkUnits)
  (Text
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     ConsistencyReport
     (AnalysisReport () () ConsistencyReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"unit checking")


unitsInfer :: Bool -> LiteralsOpt -> CamfortEnv -> IO Int
unitsInfer :: Bool -> LiteralsOpt -> CamfortEnv -> IO Int
unitsInfer Bool
showAST =
  [Char]
-> (UnitOpts
    -> AnalysisProgram () () IO (ProgramFile A) InferenceResult)
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     InferenceResult
     (AnalysisReport () () InferenceResult)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
forall e w b a.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> (UnitOpts -> AnalysisProgram e w IO a b)
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
runUnitsFunctionalityP
  [Char]
"Inferring units for"
  (UnitAnalysis InferenceResult
-> UnitOpts
-> AnalysisProgram () () IO (ProgramFile A) InferenceResult
forall a.
UnitAnalysis a
-> UnitOpts -> AnalysisProgram () () IO (ProgramFile A) a
singlePfUnits UnitAnalysis InferenceResult
inferUnits)
  (if Bool
showAST
      then AnalysisRunnerP
  ()
  ()
  IO
  (ProgramFile A)
  InferenceResult
  (AnalysisReport () () InferenceResult)
forall (m :: * -> *) w e.
(MonadIO m, Describe w, Describe e, NFData w, NFData e) =>
AnalysisRunnerP
  e
  w
  m
  (ProgramFile A)
  InferenceResult
  (AnalysisReport e w InferenceResult)
describePerFileAnalysisShowASTUnitInfoP
      else Text
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     InferenceResult
     (AnalysisReport () () InferenceResult)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"unit inference")

-- | Given an analysis program for a single file, run it over every input file
-- and collect the reports, then print those reports to standard output.
describePerFileAnalysisShowASTUnitInfoP
  :: (MonadIO m, Describe w, Describe e, NFData w, NFData e)
  => AnalysisRunnerP e w m ProgramFile InferenceResult (AnalysisReport e w InferenceResult)
describePerFileAnalysisShowASTUnitInfoP :: forall (m :: * -> *) w e.
(MonadIO m, Describe w, Describe e, NFData w, NFData e) =>
AnalysisRunnerP
  e
  w
  m
  (ProgramFile A)
  InferenceResult
  (AnalysisReport e w InferenceResult)
describePerFileAnalysisShowASTUnitInfoP AnalysisProgram e w m (ProgramFile A) InferenceResult
program LogOutput m
logOutput LogLevel
logLevel Bool
snippets ModFiles
modFiles =
  AnalysisRunnerP
  e
  w
  m
  (ProgramFile A)
  InferenceResult
  (AnalysisReport e w InferenceResult)
forall (m :: * -> *) e w b.
(MonadIO m, Describe e, Describe w, NFData e, NFData w,
 NFData b) =>
AnalysisRunnerP e w m (ProgramFile A) b (AnalysisReport e w b)
runPerFileAnalysisP AnalysisProgram e w m (ProgramFile A) InferenceResult
program LogOutput m
logOutput LogLevel
logLevel Bool
snippets ModFiles
modFiles Proxy
  ()
  (ProgramFile A, SourceText)
  ()
  (AnalysisReport e w InferenceResult)
  m
  ()
-> Proxy
     ()
     (AnalysisReport e w InferenceResult)
     ()
     (AnalysisReport e w InferenceResult)
     m
     ()
-> Proxy
     ()
     (ProgramFile A, SourceText)
     ()
     (AnalysisReport e w InferenceResult)
     m
     ()
forall (m :: * -> *) a' a b r c' c.
Functor m =>
Proxy a' a () b m r -> Proxy () b c' c m r -> Proxy a' a c' c m r
>->
    ((AnalysisReport e w InferenceResult
 -> m (AnalysisReport e w InferenceResult))
-> Proxy
     ()
     (AnalysisReport e w InferenceResult)
     ()
     (AnalysisReport e w InferenceResult)
     m
     ()
forall (m :: * -> *) a b r. Monad m => (a -> m b) -> Pipe a b m r
P.mapM ((AnalysisReport e w InferenceResult
  -> m (AnalysisReport e w InferenceResult))
 -> Proxy
      ()
      (AnalysisReport e w InferenceResult)
      ()
      (AnalysisReport e w InferenceResult)
      m
      ())
-> (AnalysisReport e w InferenceResult
    -> m (AnalysisReport e w InferenceResult))
-> Proxy
     ()
     (AnalysisReport e w InferenceResult)
     ()
     (AnalysisReport e w InferenceResult)
     m
     ()
forall a b. (a -> b) -> a -> b
$ \ AnalysisReport e w InferenceResult
r -> do
        case AnalysisReport e w InferenceResult
r of
          AnalysisReport [Char]
_ [SomeMessage e w]
_ (ARSuccess (Inferred (InferenceReport ProgramFile UA
pfUA [(VV, UnitInfo)]
_))) ->
            IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> (ProgramFile UA -> IO ()) -> ProgramFile UA -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile (Maybe UnitInfo) -> IO ()
forall a. Out a => a -> IO ()
pp (ProgramFile (Maybe UnitInfo) -> IO ())
-> (ProgramFile UA -> ProgramFile (Maybe UnitInfo))
-> ProgramFile UA
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (UA -> Maybe UnitInfo)
-> ProgramFile UA -> ProgramFile (Maybe UnitInfo)
forall a b. (a -> b) -> ProgramFile a -> ProgramFile b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (UnitAnnotation A -> Maybe UnitInfo
forall a. UnitAnnotation a -> Maybe UnitInfo
unitInfo (UnitAnnotation A -> Maybe UnitInfo)
-> (UA -> UnitAnnotation A) -> UA -> Maybe UnitInfo
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UA -> UnitAnnotation A
forall a. Analysis a -> a
FA.prevAnnotation) (ProgramFile UA -> ProgramFile (Maybe UnitInfo))
-> (ProgramFile UA -> ProgramFile UA)
-> ProgramFile UA
-> ProgramFile (Maybe UnitInfo)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile UA -> ProgramFile UA
forall a.
Data a =>
ProgramFile (Analysis a) -> ProgramFile (Analysis a)
FA.rename (ProgramFile UA -> m ()) -> ProgramFile UA -> m ()
forall a b. (a -> b) -> a -> b
$ ProgramFile UA
pfUA
          AnalysisReport e w InferenceResult
_ -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
        Text
-> Maybe LogLevel
-> Bool
-> AnalysisReport e w InferenceResult
-> m ()
forall e w r (m :: * -> *).
(Describe e, Describe w, Describe r, MonadIO m) =>
Text -> Maybe LogLevel -> Bool -> AnalysisReport e w r -> m ()
putDescribeReport Text
"unit inference" (LogLevel -> Maybe LogLevel
forall a. a -> Maybe a
Just LogLevel
logLevel) Bool
snippets AnalysisReport e w InferenceResult
r
        AnalysisReport e w InferenceResult
-> m (AnalysisReport e w InferenceResult)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure AnalysisReport e w InferenceResult
r)

-- | Expand all paths that are directories into a list of Fortran
-- files from a recursive directory listing.
expandDirs :: [FilePath] -> IO [FilePath]
expandDirs :: [[Char]] -> IO [[Char]]
expandDirs = ([[[Char]]] -> [[Char]]) -> IO [[[Char]]] -> IO [[Char]]
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[[Char]]] -> [[Char]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (IO [[[Char]]] -> IO [[Char]])
-> ([[Char]] -> IO [[[Char]]]) -> [[Char]] -> IO [[Char]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Char] -> IO [[Char]]) -> [[Char]] -> IO [[[Char]]]
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 [Char] -> IO [[Char]]
doEach
  where
    doEach :: [Char] -> IO [[Char]]
doEach [Char]
path = do
      Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
path
      if Bool
isDir
        then [Char] -> IO [[Char]]
listFortranFiles [Char]
path
        else [[Char]] -> IO [[Char]]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [[Char]
path]

-- | Get a list of Fortran files under the given directory.
listFortranFiles :: FilePath -> IO [FilePath]
listFortranFiles :: [Char] -> IO [[Char]]
listFortranFiles [Char]
dir = ([Char] -> Bool) -> [[Char]] -> [[Char]]
forall a. (a -> Bool) -> [a] -> [a]
filter [Char] -> Bool
isFortran ([[Char]] -> [[Char]]) -> IO [[Char]] -> IO [[Char]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Char] -> IO [[Char]]
listDirectoryRecursively [Char]
dir
  where
    -- | True if the file has a valid fortran extension.
    isFortran :: FilePath -> Bool
    isFortran :: [Char] -> Bool
isFortran [Char]
x = (Char -> Char) -> [Char] -> [Char]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower ([Char] -> [Char]
takeExtension [Char]
x) [Char] -> [[Char]] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [[Char]]
exts
      where exts :: [[Char]]
exts = [[Char]
".f", [Char]
".f90", [Char]
".f77", [Char]
".f03"]

listDirectoryRecursively :: FilePath -> IO [FilePath]
listDirectoryRecursively :: [Char] -> IO [[Char]]
listDirectoryRecursively [Char]
dir = [Char] -> [Char] -> IO [[Char]]
listDirectoryRec [Char]
dir [Char]
""
  where
    listDirectoryRec :: FilePath -> FilePath -> IO [FilePath]
    listDirectoryRec :: [Char] -> [Char] -> IO [[Char]]
listDirectoryRec [Char]
d [Char]
f = do
      let fullPath :: [Char]
fullPath = [Char]
d [Char] -> [Char] -> [Char]
</> [Char]
f
      Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
fullPath
      if Bool
isDir
      then do
        [[Char]]
conts <- [Char] -> IO [[Char]]
listDirectory [Char]
fullPath
        [[[Char]]] -> [[Char]]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[[Char]]] -> [[Char]]) -> IO [[[Char]]] -> IO [[Char]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([Char] -> IO [[Char]]) -> [[Char]] -> IO [[[Char]]]
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 ([Char] -> [Char] -> IO [[Char]]
listDirectoryRec [Char]
fullPath) [[Char]]
conts
      else [[Char]] -> IO [[Char]]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [[Char]
fullPath]

decodeOneModFile :: FilePath -> IO FM.ModFiles
decodeOneModFile :: [Char] -> IO ModFiles
decodeOneModFile [Char]
path = do
  ByteString
contents <- [Char] -> IO ByteString
LB.readFile [Char]
path
  case ByteString -> Either [Char] ModFiles
FM.decodeModFile ByteString
contents of
    Left [Char]
msg -> do
      Handle -> [Char] -> IO ()
hPutStrLn Handle
stderr ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
path [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": Error: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
msg
      ModFiles -> IO ModFiles
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
    Right ModFiles
modFiles -> do
      Handle -> [Char] -> IO ()
hPutStrLn Handle
stderr ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
path [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
": successfully parsed summary file."
      ModFiles -> IO ModFiles
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ModFiles
modFiles

unitsCompile :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCompile :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCompile LiteralsOpt
opts CamfortEnv
env = do
  let uo :: UnitOpts
uo = LiteralsOpt -> UnitOpts
optsToUnitOpts LiteralsOpt
opts
  let description :: [Char]
description = [Char]
"Compiling units for"
  [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
description [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" '" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ CamfortEnv -> [Char]
ceInputSources CamfortEnv
env [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"'"
  [Char]
incDir' <- IO [Char] -> ([Char] -> IO [Char]) -> Maybe [Char] -> IO [Char]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe IO [Char]
getCurrentDirectory [Char] -> IO [Char]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CamfortEnv -> Maybe [Char]
ceIncludeDir CamfortEnv
env)
  Bool
isDir <- [Char] -> IO Bool
doesDirectoryExist [Char]
incDir'
  let incDir :: [Char]
incDir | Bool
isDir     = [Char]
incDir'
             | Bool
otherwise = [Char] -> [Char]
takeDirectory [Char]
incDir'
  -- modFileNames <- getModFiles incDir

  [[Char]]
paths' <- [[Char]] -> IO [[Char]]
expandDirs ([[Char]] -> IO [[Char]]) -> [[Char]] -> IO [[Char]]
forall a b. (a -> b) -> a -> b
$ [CamfortEnv -> [Char]
ceInputSources CamfortEnv
env]
  -- Build the graph of module dependencies
  ModGraph
mg0 <- Maybe FortranVersion -> [[Char]] -> [[Char]] -> IO ModGraph
FM.genModGraph (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) [[Char]
incDir] [[Char]]
paths'

  let compileFileToMod :: ModFiles -> ProgramFile A -> IO ModFile
compileFileToMod ModFiles
mods ProgramFile A
pf = do
        ModFile
mod <- MFCompiler UnitOpts IO
compileUnits UnitOpts
uo ModFiles
mods ProgramFile A
pf
        let mfname :: [Char]
mfname = [Char] -> [Char] -> [Char]
replaceExtension (ModFile -> [Char]
FM.moduleFilename ModFile
mod) [Char]
FM.modFileSuffix
        [Char] -> ByteString -> IO ()
LB.writeFile [Char]
mfname (ModFiles -> ByteString
FM.encodeModFile [ModFile
mod])
        ModFile -> IO ModFile
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ModFile
mod

  -- Loop through the dependency graph until it is empty
  let loop :: ModGraph -> ModFiles -> IO ModFiles
loop ModGraph
mg ModFiles
mods
        | [(Int, Maybe ModOrigin)]
nxt <- ModGraph -> [(Int, Maybe ModOrigin)]
FM.takeNextMods ModGraph
mg
        , Bool -> Bool
not ([(Int, Maybe ModOrigin)] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Int, Maybe ModOrigin)]
nxt) = do
            let fnPaths :: [[Char]]
fnPaths = [ [Char]
fn | (Int
_, Just (FM.MOFile [Char]
fn)) <- [(Int, Maybe ModOrigin)]
nxt ]
            ModFiles
newMods <- ([ModFiles] -> ModFiles) -> IO [ModFiles] -> IO ModFiles
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [ModFiles] -> ModFiles
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (IO [ModFiles] -> IO ModFiles)
-> (([Char] -> IO ModFiles) -> IO [ModFiles])
-> ([Char] -> IO ModFiles)
-> IO ModFiles
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Char]] -> ([Char] -> IO ModFiles) -> IO [ModFiles]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [[Char]]
fnPaths (([Char] -> IO ModFiles) -> IO ModFiles)
-> ([Char] -> IO ModFiles) -> IO ModFiles
forall a b. (a -> b) -> a -> b
$ \ [Char]
fnPath -> do
              TimestampStatus
tsStatus <- [Char] -> IO TimestampStatus
FM.checkTimestamps [Char]
fnPath
              case TimestampStatus
tsStatus of
                TimestampStatus
FM.NoSuchFile -> do
                  [Char] -> IO ()
putStr ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Does not exist: " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
fnPath
                  ModFiles -> IO ModFiles
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ModFile
FM.emptyModFile]
                FM.ModFileExists [Char]
modPath -> do
                  [Char] -> IO ()
putStrLn ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Loading mod file " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
modPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"."
                  [Char] -> IO ModFiles
decodeOneModFile [Char]
modPath
                TimestampStatus
FM.CompileFile -> do
                  [Char] -> IO ()
putStr ([Char] -> IO ()) -> [Char] -> IO ()
forall a b. (a -> b) -> a -> b
$ [Char]
"Summarising " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
fnPath [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"..."
                  Maybe (ProgramFile A, SourceText)
m_pf <- Maybe FortranVersion
-> ModFiles -> [Char] -> IO (Maybe (ProgramFile A, SourceText))
readParseSrcFile (CamfortEnv -> Maybe FortranVersion
ceFortranVersion CamfortEnv
env) ModFiles
mods [Char]
fnPath
                  case Maybe (ProgramFile A, SourceText)
m_pf of
                    Just (ProgramFile A
pf, SourceText
_) -> do
                      ModFile
mod <- ModFiles -> ProgramFile A -> IO ModFile
compileFileToMod ModFiles
mods ProgramFile A
pf
                      [Char] -> IO ()
putStrLn [Char]
"done"
                      ModFiles -> IO ModFiles
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [ModFile
mod]
                    Maybe (ProgramFile A, SourceText)
Nothing -> do
                      [Char] -> IO ()
putStrLn [Char]
"failed"
                      ModFiles -> IO ModFiles
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []

            let ns :: [Int]
ns  = ((Int, Maybe ModOrigin) -> Int)
-> [(Int, Maybe ModOrigin)] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Maybe ModOrigin) -> Int
forall a b. (a, b) -> a
fst [(Int, Maybe ModOrigin)]
nxt
            let mg' :: ModGraph
mg' = [Int] -> ModGraph -> ModGraph
FM.delModNodes [Int]
ns ModGraph
mg
            ModGraph -> ModFiles -> IO ModFiles
loop ModGraph
mg' (ModFiles -> IO ModFiles) -> ModFiles -> IO ModFiles
forall a b. (a -> b) -> a -> b
$ ModFiles
newMods ModFiles -> ModFiles -> ModFiles
forall a. [a] -> [a] -> [a]
++ ModFiles
mods
      loop ModGraph
_ ModFiles
mods = ModFiles -> IO ModFiles
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ModFiles
mods

  ModFiles
_allMods <- ModGraph -> ModFiles -> IO ModFiles
loop ModGraph
mg0 []
  Int -> IO Int
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Int
0

unitsSynth :: AnnotationType -> FileOrDir -> LiteralsOpt -> CamfortEnv -> IO Int
unitsSynth :: AnnotationType -> [Char] -> LiteralsOpt -> CamfortEnv -> IO Int
unitsSynth AnnotationType
annType [Char]
outSrc LiteralsOpt
opts CamfortEnv
env =
  [Char]
-> AnalysisProgram
     ()
     ()
     IO
     [ProgramFile A]
     (Text, [Either ConsistencyError (ProgramFile A)])
-> AnalysisRunner
     ()
     ()
     IO
     [ProgramFile A]
     (Text, [Either ConsistencyError (ProgramFile A)])
     Int
-> MFCompiler UnitOpts IO
-> UnitOpts
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunner e w IO a b r
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO r
runFunctionality [Char]
"Synthesising units for"
                   (UnitAnalysis
  (Either ConsistencyError (InferenceReport, ProgramFile A))
-> UnitOpts
-> AnalysisProgram
     ()
     ()
     IO
     [ProgramFile A]
     (Text, [Either ConsistencyError (ProgramFile A)])
forall a e b.
Describe a =>
UnitAnalysis (Either e (a, b))
-> UnitOpts
-> AnalysisProgram () () IO [ProgramFile A] (Text, [Either e b])
multiPfUnits (Char
-> UnitAnalysis
     (Either ConsistencyError (InferenceReport, ProgramFile A))
LU.synthesiseUnits (AnnotationType -> Char
markerChar AnnotationType
annType)) UnitOpts
uo)
                   (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     ()
     ()
     IO
     [ProgramFile A]
     (Text, [Either ConsistencyError (ProgramFile A)])
     Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"unit synthesis" (CamfortEnv -> [Char]
ceInputSources CamfortEnv
env) [Char]
outSrc)
                   MFCompiler UnitOpts IO
compileUnits
                   UnitOpts
uo
                   CamfortEnv
env
  where uo :: UnitOpts
uo = LiteralsOpt -> UnitOpts
optsToUnitOpts LiteralsOpt
opts

unitsCriticals :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCriticals :: LiteralsOpt -> CamfortEnv -> IO Int
unitsCriticals =
  [Char]
-> (UnitOpts -> AnalysisProgram () () IO (ProgramFile A) Criticals)
-> AnalysisRunnerP
     () () IO (ProgramFile A) Criticals (AnalysisReport () () Criticals)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
forall e w b a.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> (UnitOpts -> AnalysisProgram e w IO a b)
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> LiteralsOpt
-> CamfortEnv
-> IO Int
runUnitsFunctionalityP
  [Char]
"Suggesting variables to annotate with unit specifications in"
  (UnitAnalysis Criticals
-> UnitOpts -> AnalysisProgram () () IO (ProgramFile A) Criticals
forall a.
UnitAnalysis a
-> UnitOpts -> AnalysisProgram () () IO (ProgramFile A) a
singlePfUnits UnitAnalysis Criticals
inferCriticalVariables)
  (Text
-> AnalysisRunnerP
     () () IO (ProgramFile A) Criticals (AnalysisReport () () Criticals)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"unit critical variable analysis")


{- Stencils feature -}


stencilsCheck :: CamfortEnv -> IO Int
stencilsCheck :: CamfortEnv -> IO Int
stencilsCheck =
  [Char]
-> AnalysisProgram () () IO (ProgramFile A) CheckResult
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     CheckResult
     (AnalysisReport () () CheckResult)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking stencil specs for"
  (PureAnalysis () () CheckResult -> AnalysisT () () IO CheckResult
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis () () CheckResult -> AnalysisT () () IO CheckResult)
-> (ProgramFile A -> PureAnalysis () () CheckResult)
-> AnalysisProgram () () IO (ProgramFile A) CheckResult
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProgramFile A -> PureAnalysis () () CheckResult
Stencils.check)
  (Text
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     CheckResult
     (AnalysisReport () () CheckResult)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"stencil checking")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
compileStencils ()


stencilsInfer :: Bool -> CamfortEnv -> IO Int
stencilsInfer :: Bool -> CamfortEnv -> IO Int
stencilsInfer Bool
useEval =
  [Char]
-> AnalysisProgram () () IO (ProgramFile A) StencilsReport
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     StencilsReport
     (AnalysisReport () () StencilsReport)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Inferring stencil specs for"
  (PureAnalysis () () StencilsReport
-> AnalysisT () () IO StencilsReport
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis () () StencilsReport
 -> AnalysisT () () IO StencilsReport)
-> (ProgramFile A -> PureAnalysis () () StencilsReport)
-> AnalysisProgram () () IO (ProgramFile A) StencilsReport
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Char -> ProgramFile A -> PureAnalysis () () StencilsReport
Stencils.infer Bool
useEval Char
'=')
  (Text
-> AnalysisRunnerP
     ()
     ()
     IO
     (ProgramFile A)
     StencilsReport
     (AnalysisReport () () StencilsReport)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"stencil inference")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
compileStencils ()


stencilsSynth :: AnnotationType -> FileOrDir -> CamfortEnv -> IO Int
stencilsSynth :: AnnotationType -> [Char] -> CamfortEnv -> IO Int
stencilsSynth AnnotationType
annType =
  let
    program :: AnalysisProgram () () IO [ProgramFile] ((), [Either () ProgramFile])
    program :: AnalysisProgram
  () () IO [ProgramFile A] ((), [Either () (ProgramFile A)])
program [ProgramFile A]
pfs = PureAnalysis () () ((), [Either () (ProgramFile A)])
-> AnalysisT () () IO ((), [Either () (ProgramFile A)])
forall (m :: * -> *) e w a.
Monad m =>
PureAnalysis e w a -> AnalysisT e w m a
generalizePureAnalysis (PureAnalysis () () ((), [Either () (ProgramFile A)])
 -> AnalysisT () () IO ((), [Either () (ProgramFile A)]))
-> PureAnalysis () () ((), [Either () (ProgramFile A)])
-> AnalysisT () () IO ((), [Either () (ProgramFile A)])
forall a b. (a -> b) -> a -> b
$ do
      [ProgramFile A]
pfs' <- Char -> [ProgramFile A] -> StencilsAnalysis [ProgramFile A]
Stencils.synth (AnnotationType -> Char
markerChar AnnotationType
annType) [ProgramFile A]
pfs
      ((), [Either () (ProgramFile A)])
-> PureAnalysis () () ((), [Either () (ProgramFile A)])
forall a. a -> AnalysisT () () Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ((), (ProgramFile A -> Either () (ProgramFile A))
-> [ProgramFile A] -> [Either () (ProgramFile A)]
forall a b. (a -> b) -> [a] -> [b]
map ProgramFile A -> Either () (ProgramFile A)
forall a b. b -> Either a b
Right [ProgramFile A]
pfs')

  in [Char]
-> AnalysisProgram
     () () IO [ProgramFile A] ((), [Either () (ProgramFile A)])
-> ([Char]
    -> [Char]
    -> AnalysisRunner
         () () IO [ProgramFile A] ((), [Either () (ProgramFile A)]) Int)
-> MFCompiler () IO
-> ()
-> [Char]
-> CamfortEnv
-> IO Int
forall e w a b r i.
(Describe e, Describe w) =>
[Char]
-> AnalysisProgram e w IO a b
-> ([Char] -> [Char] -> AnalysisRunner e w IO a b r)
-> MFCompiler i IO
-> i
-> [Char]
-> CamfortEnv
-> IO r
runWithOutput
     [Char]
"Synthesising stencil specs for"
     AnalysisProgram
  () () IO [ProgramFile A] ((), [Either () (ProgramFile A)])
program
     (Text
-> [Char]
-> [Char]
-> AnalysisRunner
     () () IO [ProgramFile A] ((), [Either () (ProgramFile A)]) Int
forall e e' w r.
(Describe e, Describe e', Describe w, Describe r,
 ExitCodeOfReport r) =>
Text
-> [Char]
-> [Char]
-> AnalysisRunner
     e w IO [ProgramFile A] (r, [Either e' (ProgramFile A)]) Int
doRefactor Text
"stencil synthesis")
     MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
compileStencils ()

{- Invariants Feature-}

invariantsCheck :: Hoare.PrimReprOption -> CamfortEnv -> IO Int
invariantsCheck :: PrimReprOption -> CamfortEnv -> IO Int
invariantsCheck PrimReprOption
pro =
  [Char]
-> AnalysisProgram
     HoareFrontendError
     HoareFrontendWarning
     IO
     (ProgramFile A)
     HoareCheckResults
-> AnalysisRunnerP
     HoareFrontendError
     HoareFrontendWarning
     IO
     (ProgramFile A)
     HoareCheckResults
     (AnalysisReport
        HoareFrontendError HoareFrontendWarning HoareCheckResults)
-> MFCompiler () IO
-> ()
-> CamfortEnv
-> IO Int
forall e w b a i.
(Describe e, Describe w, ExitCodeOfReport b) =>
[Char]
-> AnalysisProgram e w IO a b
-> AnalysisRunnerP e w IO a b (AnalysisReport e w b)
-> MFCompiler i IO
-> i
-> CamfortEnv
-> IO Int
runFunctionalityP
  [Char]
"Checking invariants in"
  (PrimReprOption
-> AnalysisProgram
     HoareFrontendError
     HoareFrontendWarning
     IO
     (ProgramFile A)
     HoareCheckResults
Hoare.check PrimReprOption
pro)
  (Text
-> AnalysisRunnerP
     HoareFrontendError
     HoareFrontendWarning
     IO
     (ProgramFile A)
     HoareCheckResults
     (AnalysisReport
        HoareFrontendError HoareFrontendWarning HoareCheckResults)
forall (m :: * -> *) r w e.
(MonadIO m, Describe r, ExitCodeOfReport r, Describe w, Describe e,
 NFData e, NFData w, NFData r) =>
Text
-> AnalysisRunnerP e w m (ProgramFile A) r (AnalysisReport e w r)
describePerFileAnalysisP Text
"invariant checking")
  MFCompiler () IO
forall (m :: * -> *). Monad m => MFCompiler () m
simpleCompiler ()


-- | Initialize Camfort for the given project.
camfortInitialize :: FilePath -> IO ()
camfortInitialize :: [Char] -> IO ()
camfortInitialize [Char]
projectDir =
  Bool -> [Char] -> IO ()
createDirectoryIfMissing Bool
False ([Char]
projectDir [Char] -> [Char] -> [Char]
</> [Char]
".camfort")