camfort-0.903: src/Camfort/Functionality.hs
{-
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 DeriveDataTypeable #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Camfort.Functionality (
-- * Datatypes
AnnotationType(..)
-- * Commands
, ast
, countVarDecls
-- ** Stencil Analysis
, stencilsCheck
, stencilsInfer
, stencilsSynth
-- ** Unit Analysis
, unitsCriticals
, unitsCheck
, unitsInfer
, unitsSynth
, unitsCompile
-- ** Refactorings
, common
, dead
, equivalences
) where
import Control.Monad
import System.FilePath (takeDirectory)
import Camfort.Analysis.Simple
import Camfort.Transformation.DeadCode
import Camfort.Transformation.CommonBlockElim
import Camfort.Transformation.EquivalenceElim
import qualified Camfort.Specification.Units as LU
import Camfort.Specification.Units.Monad
import Camfort.Helpers
import Camfort.Input
import Language.Fortran.Util.ModFile
import qualified Camfort.Specification.Stencils as Stencils
import qualified Data.Map.Strict as M
data AnnotationType = ATDefault | Doxygen | Ford
-- | Retrieve the marker character compatible with the given
-- type of annotation.
markerChar :: AnnotationType -> Char
markerChar Doxygen = '<'
markerChar Ford = '!'
markerChar ATDefault = '='
-- * Wrappers on all of the features
ast d excludes = do
xs <- readParseSrcDir d excludes
print . fmap fst $ xs
countVarDecls inSrc excludes = do
putStrLn $ "Counting variable declarations in '" ++ inSrc ++ "'"
doAnalysisSummary countVariableDeclarations inSrc excludes
dead inSrc excludes outSrc = do
putStrLn $ "Eliminating dead code in '" ++ inSrc ++ "'"
report <- doRefactor (mapM (deadCode False)) inSrc excludes outSrc
putStrLn report
common inSrc excludes outSrc = do
putStrLn $ "Refactoring common blocks in '" ++ inSrc ++ "'"
isDir <- isDirectory inSrc
let rfun = commonElimToModules (takeDirectory outSrc ++ "/")
report <- doRefactorAndCreate rfun inSrc excludes outSrc
putStrLn report
equivalences inSrc excludes outSrc = do
putStrLn $ "Refactoring equivalences blocks in '" ++ inSrc ++ "'"
report <- doRefactor (mapM refactorEquivalences) inSrc excludes outSrc
putStrLn report
{- Units feature -}
optsToUnitOpts :: LiteralsOpt -> Bool -> Maybe String -> IO UnitOpts
optsToUnitOpts m debug = maybe (pure o1)
(fmap (\modFiles -> o1 { uoModFiles = M.fromList modFiles }) . getModFilesWithNames)
where o1 = unitOpts0 { uoLiterals = m
, uoDebug = debug
, uoModFiles = M.empty }
unitsCheck inSrc excludes m debug incDir = do
putStrLn $ "Checking units for '" ++ inSrc ++ "'"
uo <- optsToUnitOpts m debug incDir
let rfun = concatMap (LU.checkUnits uo)
doAnalysisReportWithModFiles rfun putStrLn inSrc incDir excludes
unitsInfer inSrc excludes m debug incDir = do
putStrLn $ "Inferring units for '" ++ inSrc ++ "'"
uo <- optsToUnitOpts m debug incDir
let rfun = concatMap (LU.inferUnits uo)
doAnalysisReportWithModFiles rfun putStrLn inSrc incDir excludes
unitsCompile inSrc excludes m debug incDir outSrc = do
putStrLn $ "Compiling units for '" ++ inSrc ++ "'"
uo <- optsToUnitOpts m debug incDir
let rfun = LU.compileUnits uo
putStrLn =<< doCreateBinary rfun inSrc incDir excludes outSrc
unitsSynth inSrc excludes m debug incDir outSrc annType = do
putStrLn $ "Synthesising units for '" ++ inSrc ++ "'"
let marker = markerChar annType
uo <- optsToUnitOpts m debug incDir
let rfun =
mapM (LU.synthesiseUnits uo marker)
report <- doRefactorWithModFiles rfun inSrc incDir excludes outSrc
putStrLn report
unitsCriticals inSrc excludes m debug incDir = do
putStrLn $ "Suggesting variables to annotate with unit specifications in '"
++ inSrc ++ "'"
uo <- optsToUnitOpts m debug incDir
let rfun = mapM (LU.inferCriticalVariables uo)
doAnalysisReportWithModFiles rfun (putStrLn . fst) inSrc incDir excludes
{- Stencils feature -}
stencilsCheck inSrc excludes = do
putStrLn $ "Checking stencil specs for '" ++ inSrc ++ "'"
let rfun p = (Stencils.check p, p)
doAnalysisSummary rfun inSrc excludes
stencilsInfer inSrc excludes inferMode = do
putStrLn $ "Inferring stencil specs for '" ++ inSrc ++ "'"
let rfun = Stencils.infer inferMode '='
doAnalysisSummary rfun inSrc excludes
stencilsSynth inSrc excludes inferMode annType outSrc = do
putStrLn $ "Synthesising stencil specs for '" ++ inSrc ++ "'"
let rfun = Stencils.synth inferMode (markerChar annType)
report <- doRefactor rfun inSrc excludes outSrc
putStrLn report