1
module HpcOverlay where
12
overlay_options :: FlagOptSeq
18
overlay_plugin :: Plugin
19
overlay_plugin = Plugin { name = "overlay"
20
, usage = "[OPTION] .. <OVERLAY_FILE> [<OVERLAY_FILE> [...]]"
21
, options = overlay_options
22
, summary = "Generate a .tix file from an overlay file"
23
, implementation = overlay_main
24
, init_flags = default_flags
25
, final_flags = default_final_flags
28
overlay_main :: Flags -> [String] -> IO ()
29
overlay_main _ [] = hpcError overlay_plugin $ "no overlay file specified"
30
overlay_main flags files = do
31
specs <- mapM hpcParser files
32
let (Spec globals modules) = concatSpec specs
34
let modules1 = Map.fromListWith (++) [ (m,info) | (m,info) <- modules ]
37
sequence [ do mix@(Mix origFile _ _ _ _) <- readMixWithFlags flags (Left modu)
38
content <- readFileFromPath (hpcError overlay_plugin) origFile (srcDirs flags)
39
processModule modu content mix mod_spec globals
40
| (modu, mod_spec) <- Map.toList modules1
44
let tix = Tix $ mod_info
46
case outputFile flags of
47
"-" -> putStrLn (show tix)
48
out -> writeFile out (show tix)
51
processModule :: String -- ^ module name
52
-> String -- ^ module contents
53
-> Mix -- ^ mix entry for this module
54
-> [Tick] -- ^ local ticks
55
-> [ExprTick] -- ^ global ticks
57
processModule modName modContents (Mix _ _ hash _ entries) locals globals = do
59
let hsMap :: Map.Map Int String
60
hsMap = Map.fromList (zip [1..] $ lines modContents)
62
let topLevelFunctions =
65
| (pos,TopLevelBox [nm]) <- entries
68
let inside :: HpcPos -> String -> Bool
70
case Map.lookup nm topLevelFunctions of
72
Just poss -> any (pos `insideHpcPos`) poss
74
-- TODO: rename plzTick => plzExprTick, plzTopPick => plzTick
75
let plzTick :: HpcPos -> BoxLabel -> ExprTick -> Bool
76
plzTick pos (ExpBox _) (TickExpression _ match q _) =
80
Just str -> str == grabHpcPos hsMap pos
84
plzTopTick :: HpcPos -> BoxLabel -> Tick -> Bool
85
plzTopTick pos label (ExprTick ignore) = plzTick pos label ignore
86
plzTopTick pos _ (TickFunction fn q _) =
87
qualifier pos q && pos `inside` fn
88
plzTopTick pos label (InsideFunction fn igs) =
89
pos `inside` fn && any (plzTopTick pos label) igs
92
let tixs = Map.fromList
94
any (plzTick pos label) globals
95
|| any (plzTopTick pos label) locals)
96
| (ix,(pos,label)) <- zip [0..] entries
100
-- let show' (srcspan,stuff) = show (srcspan,stuff,grabHpcPos hsMap span)
102
let forest = createMixEntryDom
104
| ((srcspan,_),ix) <- zip entries [0..]
109
let forest2 = addParentToList [] $ forest
110
-- putStrLn $ drawForest $ map (fmap show') $ forest2
112
let isDomList = Map.fromList
113
[ (ix,filter (/= ix) rng ++ dom)
114
| (_,(rng,dom)) <- concatMap flatten forest2
118
-- We do not use laziness here, because the dominator lists
119
-- point to their equivent peers, creating loops.
123
case Map.lookup n tixs of
125
Nothing -> error $ "can not find ix # " ++ show n
127
let tixs' = [ case Map.lookup n isDomList of
128
Just vs -> if any isTicked (n : vs) then 1 else 0
129
Nothing -> error $ "can not find ix in dom list # " ++ show n
130
| n <- [0..(length entries - 1)]
133
return $ TixModule modName hash (length tixs') tixs'
135
qualifier :: HpcPos -> Maybe Qualifier -> Bool
136
qualifier _ Nothing = True
137
qualifier pos (Just (OnLine n)) = n == l1 && n == l2
138
where (l1,_,l2,_) = fromHpcPos pos
139
qualifier pos (Just (AtPosition l1' c1' l2' c2'))
140
= (l1', c1', l2', c2') == fromHpcPos pos
142
concatSpec :: [Spec] -> Spec
144
(\ (Spec pre1 body1) (Spec pre2 body2)
145
-> Spec (pre1 ++ pre2) (body1 ++ body2))
150
addParentToTree :: [a] -> MixEntryDom [a] -> MixEntryDom ([a],[a])
151
addParentToTree path (Node (pos,a) children) =
152
Node (pos,(a,path)) (addParentToList (a ++ path) children)
154
addParentToList :: [a] -> [MixEntryDom [a]] -> [MixEntryDom ([a],[a])]
155
addParentToList path nodes = map (addParentToTree path) nodes