module Camfort.Specification.Stencils
(InferMode, infer, check, synth) where
import Camfort.Specification.Stencils.CheckFrontend hiding (LogLine)
import Camfort.Specification.Stencils.InferenceFrontend
import Camfort.Specification.Stencils.Synthesis
import Camfort.Analysis.Annotations
import Camfort.Helpers
import qualified Language.Fortran.AST as F
import qualified Language.Fortran.Analysis as FA
import qualified Language.Fortran.Analysis.Renaming as FAR
import qualified Language.Fortran.Analysis.BBlocks as FAB
import Data.List
infer :: InferMode -> Char -> Filename
-> F.ProgramFile Annotation
-> (String, F.ProgramFile Annotation)
infer mode marker filename pf =
if null output
then ("", fmap FA.prevAnnotation pf'')
else ("\n" ++ filename ++ "\n" ++ output, fmap FA.prevAnnotation pf'')
where
output = intercalate "\n"
. filter (not . white)
. map (formatSpec Nothing nameMap) $ results
white = all (\x -> (x == ' ') || (x == '\t'))
(pf'', results) = stencilInference nameMap mode marker
. FAB.analyseBBlocks $ pf'
nameMap = FAR.extractNameMap pf'
pf' = FAR.analyseRenames . FA.initAnalysis $ pf
synth :: InferMode
-> Char
-> [(Filename, F.ProgramFile A)]
-> (String, [(Filename, F.ProgramFile Annotation)])
synth mode marker = foldr buildOutput ("", [])
where
buildOutput (f, pf) (r, pfs) = (r ++ r', (f, pf') : pfs)
where (r', pf') = synthPF mode marker f pf
synthPF :: InferMode -> Char -> Filename
-> F.ProgramFile Annotation
-> (String, F.ProgramFile Annotation)
synthPF _ marker _ pf =
("", fmap FA.prevAnnotation pf'')
where
(pf'', _) = stencilInference nameMap Synth marker
. FAB.analyseBBlocks $ pf'
nameMap = FAR.extractNameMap pf'
pf' = FAR.analyseRenames . FA.initAnalysis $ pf
check :: Filename -> F.ProgramFile Annotation -> String
check filename pf =
if null output then "" else "\n" ++ filename ++ "\n" ++ output
where
output = intercalate "\n" results
results = stencilChecking nameMap . FAB.analyseBBlocks $ pf'
nameMap = FAR.extractNameMap pf'
pf' = FAR.analyseRenames . FA.initAnalysis $ pf