1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
-----------------------------------------------------------------------
--- This module defines a datatype to represent the analysis information.
---
--- @author Heiko Hoffmann, Michael Hanus
--- @version January 2015
-----------------------------------------------------------------------
module GenericProgInfo
( ProgInfo, emptyProgInfo, lookupProgInfo, combineProgInfo
, lists2ProgInfo, publicListFromProgInfo, progInfo2Lists, progInfo2XML
, mapProgInfo, publicProgInfo
, showProgInfo, equalProgInfo
, readAnalysisFiles, readAnalysisPublicFile, writeAnalysisFiles
) where
import Configuration(debugMessage)
import Directory(removeFile)
import FiniteMap
import FilePath((<.>))
import FlatCurry.Types
import XML
--- Type to represent analysis information.
--- The first component are public declarations, the second the private ones.
data ProgInfo a = ProgInfo (FM QName a) (FM QName a)
--- The empty program information.
emptyProgInfo:: ProgInfo a
emptyProgInfo = ProgInfo (emptyFM (<)) (emptyFM (<))
--- Gets the information about an entity.
lookupProgInfo:: QName -> ProgInfo a -> Maybe a
lookupProgInfo key (ProgInfo map1 map2) =
case lookupFM map1 key of
Just x -> Just x
Nothing -> lookupFM map2 key
--- Combines two analysis informations.
combineProgInfo :: ProgInfo a -> ProgInfo a -> ProgInfo a
combineProgInfo (ProgInfo x1 x2) (ProgInfo y1 y2) =
ProgInfo (plusFM x1 y1) (plusFM x2 y2)
--- Converts a public and a private analysis list into a program info.
lists2ProgInfo :: ([(QName,a)],[(QName,a)]) -> ProgInfo a
lists2ProgInfo (xs,ys) = ProgInfo (listToFM (<) xs) (listToFM (<) ys)
--- Returns the infos of public operations as a list.
publicListFromProgInfo:: ProgInfo a -> [(QName,a)]
publicListFromProgInfo (ProgInfo fm1 _) = fmToList fm1
--- Transforms a program information into a pair of lists
--- containing the information about public and private entities.
progInfo2Lists :: ProgInfo a -> ([(QName,a)],[(QName,a)])
progInfo2Lists (ProgInfo map1 map2)= (fmToList map1,fmToList map2)
--- Transforms analysis information into XML format.
progInfo2XML :: ProgInfo String -> ([XmlExp],[XmlExp])
progInfo2XML (ProgInfo map1 map2) =
(foldFM entry2xml [] map1, foldFM entry2xml [] map2)
where
entry2xml (mname,name) value xmlList =
(xml "operation" [xml "module" [xtxt mname],
xml "name" [xtxt name],
xml "result" [xtxt value]]) : xmlList
mapProgInfo:: (a->b) -> ProgInfo a -> ProgInfo b
mapProgInfo func (ProgInfo map1 map2) =
ProgInfo (mapFM (\_ b->func b) map1) (mapFM (\_ b->func b) map2)
--- Transforms a program information into a program information
--- about interface entities only.
publicProgInfo :: ProgInfo a -> ProgInfo a
publicProgInfo (ProgInfo pub _) = ProgInfo pub (emptyFM (<))
--- Show a ProgInfo as a string (used for debugging only).
showProgInfo :: ProgInfo _ -> String
showProgInfo (ProgInfo fm1 fm2) =
"Public: "++showFM fm1++"\nPrivate: "++showFM fm2
-- Equality on ProgInfo
equalProgInfo :: ProgInfo a -> ProgInfo a -> Bool
equalProgInfo (ProgInfo pi1p pi1v) (ProgInfo pi2p pi2v) =
eqFM pi1p pi2p && eqFM pi1v pi2v
--- Writes a ProgInfo into a file.
writeAnalysisFiles :: String -> ProgInfo _ -> IO ()
writeAnalysisFiles basefname (ProgInfo pub priv) = do
debugMessage 3 $ "Writing analysis files '"++basefname++"'..."
writeFile (basefname <.> "priv") (showFM priv)
writeFile (basefname <.> "pub") (showFM pub)
--- Reads a ProgInfo from the analysis files where the base file name is given.
readAnalysisFiles :: String -> IO (ProgInfo _)
readAnalysisFiles basefname = do
debugMessage 3 $ "Reading analysis files '"++basefname++"'..."
let pubcontfile = basefname <.> "pub"
privcontfile = basefname <.> "priv"
pubcont <- readFile pubcontfile
privcont <- readFile privcontfile
let pinfo = ProgInfo (readFM (<) pubcont) (readFM (<) privcont)
catch (return $!! pinfo)
(\err -> do
putStrLn ("Buggy analysis files detected and removed:\n"++
basefname)
mapIO_ removeFile [pubcontfile,privcontfile]
putStrLn "Please try to re-run the analysis!"
ioError err)
--- Reads the public ProgInfo from the public analysis file.
readAnalysisPublicFile :: String -> IO (ProgInfo _)
readAnalysisPublicFile fname = do
debugMessage 3 $ "Reading public analysis file '"++fname++"'..."
fcont <- readFile fname
let pinfo = ProgInfo (readFM (<) fcont) (emptyFM (<))
catch (return $!! pinfo)
(\err -> do
putStrLn ("Buggy analysis files detected and removed:\n"++fname)
removeFile fname
putStrLn "Please try to re-run the analysis!"
ioError err)
-----------------------------------------------------------------------
|