Add rebindable syntax for if-then-else
[ghc-hetmet.git] / compiler / deSugar / Coverage.lhs
index 929141e..d894523 100644 (file)
@@ -11,7 +11,7 @@ import HsSyn
 import Module
 import Outputable
 import DynFlags
-import Monad           
+import Control.Monad
 import SrcLoc
 import ErrUtils
 import Name
@@ -23,10 +23,10 @@ import FastString
 import HscTypes        
 import StaticFlags
 import TyCon
-import FiniteMap
+import MonadUtils
+import Maybes
 
 import Data.Array
-import System.IO   (FilePath)
 import System.Directory ( createDirectoryIfMissing )
 
 import Trace.Hpc.Mix
@@ -34,6 +34,8 @@ import Trace.Hpc.Util
 
 import BreakArray 
 import Data.HashTable   ( hashString )
+import Data.Map (Map)
+import qualified Data.Map as Map
 \end{code}
 
 
@@ -52,25 +54,31 @@ addCoverageTicksToBinds
         -> LHsBinds Id
         -> IO (LHsBinds Id, HpcInfo, ModBreaks)
 
-addCoverageTicksToBinds dflags mod mod_loc tyCons binds = do 
-
-  let orig_file = 
-             case ml_hs_file mod_loc of
-                   Just file -> file
-                   Nothing -> panic "can not find the original file during hpc trans"
+addCoverageTicksToBinds dflags mod mod_loc tyCons binds = 
+ case ml_hs_file mod_loc of
+ Nothing -> return (binds, emptyHpcInfo False, emptyModBreaks)
+ Just orig_file -> do
 
   if "boot" `isSuffixOf` orig_file then return (binds, emptyHpcInfo False, emptyModBreaks) else do
 
+  -- Now, we try look for a file generated from a .hsc file to a .hs file, by peeking ahead.
+
+  let top_pos = catMaybes $ foldrBag (\ (L pos _) rest -> srcSpanFileName_maybe pos : rest) [] binds
+  let orig_file2 = case top_pos of
+                    (file_name:_) 
+                      | ".hsc" `isSuffixOf` unpackFS file_name -> unpackFS file_name
+                    _ -> orig_file
+
   let mod_name = moduleNameString (moduleName mod)
 
   let (binds1,_,st)
                 = unTM (addTickLHsBinds binds) 
                   (TTE
-                      { fileName    = mkFastString orig_file
+                      { fileName    = mkFastString orig_file2
                      , declPath     = []
                       , inScope      = emptyVarSet
-                     , blackList    = listToFM [ (getSrcSpan (tyConName tyCon),()) 
-                                               | tyCon <- tyCons ]
+                     , blackList    = Map.fromList [ (getSrcSpan (tyConName tyCon),()) 
+                                                   | tyCon <- tyCons ]
                       })
                   (TT 
                      { tickBoxCount = 0
@@ -89,14 +97,14 @@ addCoverageTicksToBinds dflags mod mod_loc tyCons binds = do
 
      let tabStop = 1 -- <tab> counts as a normal char in GHC's location ranges.
      createDirectoryIfMissing True hpc_mod_dir
-     modTime <- getModificationTime orig_file
+     modTime <- getModificationTime orig_file2
      let entries' = [ (hpcPos, box) 
                     | (span,_,box) <- entries, hpcPos <- [mkHpcPos span] ]
      when (length entries' /= tickBoxCount st) $ do
        panic "the number of .mix entries are inconsistent"
-     let hashNo = mixHash orig_file modTime tabStop entries'
+     let hashNo = mixHash orig_file2 modTime tabStop entries'
      mixCreate hpc_mod_dir mod_name 
-              $ Mix orig_file modTime (toHash hashNo) tabStop entries'
+              $ Mix orig_file2 modTime (toHash hashNo) tabStop entries'
      return $ hashNo 
    else do
      return $ 0
@@ -131,9 +139,9 @@ addTickLHsBinds :: LHsBinds Id -> TM (LHsBinds Id)
 addTickLHsBinds binds = mapBagM addTickLHsBind binds
 
 addTickLHsBind :: LHsBind Id -> TM (LHsBind Id)
-addTickLHsBind (L pos (AbsBinds abs_tvs abs_dicts abs_exports abs_binds)) = do
-  abs_binds' <- addTickLHsBinds abs_binds
-  return $ L pos $ AbsBinds abs_tvs abs_dicts abs_exports abs_binds'
+addTickLHsBind (L pos bind@(AbsBinds { abs_binds = binds })) = do
+  binds' <- addTickLHsBinds binds
+  return $ L pos $ bind { abs_binds = binds' }
 addTickLHsBind (L pos (funBind@(FunBind { fun_id = (L _ id)  }))) = do 
   let name = getOccString id
   decl_path <- getPathEntry
@@ -238,9 +246,9 @@ addTickLHsExprOptAlt oneOfMany (L pos e0)
         addTickHsExpr e0
 
 addBinTickLHsExpr :: (Bool -> BoxLabel) -> LHsExpr Id -> TM (LHsExpr Id)
-addBinTickLHsExpr boxLabel (L pos e0) = do
-    e1 <- addTickHsExpr e0
-    allocBinTickBox boxLabel $ L pos e1
+addBinTickLHsExpr boxLabel (L pos e0) =
+    allocBinTickBox boxLabel pos $
+        addTickHsExpr e0
 
 addTickHsExpr :: HsExpr Id -> TM (HsExpr Id)
 addTickHsExpr e@(HsVar id) = do freeVar id; return e
@@ -270,17 +278,21 @@ addTickHsExpr (SectionR e1 e2) =
        liftM2 SectionR
                (addTickLHsExpr e1)
                (addTickLHsExpr e2)
+addTickHsExpr (ExplicitTuple es boxity) =
+        liftM2 ExplicitTuple
+                (mapM addTickTupArg es)
+                (return boxity)
 addTickHsExpr (HsCase e mgs) = 
        liftM2 HsCase
                (addTickLHsExpr e) 
                (addTickMatchGroup mgs)
-addTickHsExpr (HsIf     e1 e2 e3) = 
-       liftM3 HsIf
+addTickHsExpr (HsIf cnd e1 e2 e3) = 
+       liftM3 (HsIf cnd)
                (addBinTickLHsExpr (BinBox CondBinBox) e1)
                (addTickLHsExprOptAlt True e2)
                (addTickLHsExprOptAlt True e3)
 addTickHsExpr (HsLet binds e) =
-       bindLocals (map unLoc $ collectLocalBinders binds) $
+       bindLocals (collectLocalBinders binds) $
        liftM2 HsLet
                (addTickHsLocalBinds binds) -- to think about: !patterns.
                 (addTickLHsExprNeverOrAlways e)
@@ -293,17 +305,13 @@ addTickHsExpr (HsDo cxt stmts last_exp srcloc) = do
                    ListComp -> Just $ BinBox QualBinBox
                    _        -> Nothing
 addTickHsExpr (ExplicitList ty es) = 
-       liftM2 ExplicitList 
+       liftM2 ExplicitList
                (return ty)
                (mapM (addTickLHsExpr) es)
 addTickHsExpr (ExplicitPArr ty es) =
        liftM2 ExplicitPArr
                (return ty)
                (mapM (addTickLHsExpr) es)
-addTickHsExpr (ExplicitTuple es box) =
-       liftM2 ExplicitTuple
-               (mapM (addTickLHsExpr) es)
-               (return box)
 addTickHsExpr (RecordCon id ty rec_binds) = 
        liftM3 RecordCon
                (return id)
@@ -369,6 +377,10 @@ addTickHsExpr e@(HsType _) = return e
 -- Others dhould never happen in expression content.
 addTickHsExpr e  = pprPanic "addTickHsExpr" (ppr e)
 
+addTickTupArg :: HsTupArg Id -> TM (HsTupArg Id)
+addTickTupArg (Present e)  = do { e' <- addTickLHsExpr e; return (Present e') }
+addTickTupArg (Missing ty) = return (Missing ty)
+
 addTickMatchGroup :: MatchGroup Id -> TM (MatchGroup Id)
 addTickMatchGroup (MatchGroup matches ty) = do
   let isOneOfMany = matchesOneOfMany matches
@@ -388,7 +400,7 @@ addTickGRHSs isOneOfMany (GRHSs guarded local_binds) = do
     guarded' <- mapM (liftL (addTickGRHS isOneOfMany)) guarded
     return $ GRHSs guarded' local_binds'
   where
-    binders = map unLoc (collectLocalBinders local_binds)
+    binders = collectLocalBinders local_binds
 
 addTickGRHS :: Bool -> GRHS Id -> TM (GRHS Id)
 addTickGRHS isOneOfMany (GRHS stmts expr) = do
@@ -410,7 +422,7 @@ addTickLStmts' isGuard lstmts res
         a <- res
         return (lstmts', a)
   where
-        binders = map unLoc (collectLStmtsBinders lstmts)
+        binders = collectLStmtsBinders lstmts
 
 addTickStmt :: (Maybe (Bool -> BoxLabel)) -> Stmt Id -> TM (Stmt Id)
 addTickStmt _isGuard (BindStmt pat e bind fail) = do
@@ -430,32 +442,30 @@ addTickStmt _isGuard (LetStmt binds) = do
 addTickStmt isGuard (ParStmt pairs) = do
     liftM ParStmt 
         (mapM (addTickStmtAndBinders isGuard) pairs)
-addTickStmt isGuard (TransformStmt (stmts, ids) usingExpr maybeByExpr) = do
-    liftM3 TransformStmt 
-        (addTickStmtAndBinders isGuard (stmts, ids))
+
+addTickStmt isGuard (TransformStmt stmts ids usingExpr maybeByExpr) = do
+    liftM4 TransformStmt 
+        (addTickLStmts isGuard stmts)
+        (return ids)
         (addTickLHsExprAlways usingExpr)
         (addTickMaybeByLHsExpr maybeByExpr)
-addTickStmt isGuard (GroupStmt (stmts, binderMap) groupByClause) = do
-    liftM2 GroupStmt 
-        (addTickStmtAndBinders isGuard (stmts, binderMap))
-        (case groupByClause of
-            GroupByNothing usingExpr -> addTickLHsExprAlways usingExpr >>= (return . GroupByNothing)
-            GroupBySomething eitherUsingExpr byExpr -> do
-                eitherUsingExpr' <- mapEitherM addTickLHsExprAlways (addTickSyntaxExpr hpcSrcSpan) eitherUsingExpr
-                byExpr' <- addTickLHsExprAlways byExpr
-                return $ GroupBySomething eitherUsingExpr' byExpr')
-    where
-        mapEitherM f g x = do
-          case x of
-            Left a -> f a >>= (return . Left)
-            Right b -> g b >>= (return . Right)
-addTickStmt isGuard (RecStmt stmts ids1 ids2 tys dictbinds) = do
-       liftM5 RecStmt 
-               (addTickLStmts isGuard stmts)
-               (return ids1)
-               (return ids2)
-               (return tys)
-               (addTickDictBinds dictbinds)
+
+addTickStmt isGuard (GroupStmt stmts binderMap by using) = do
+    liftM4 GroupStmt 
+        (addTickLStmts isGuard stmts)
+        (return binderMap)
+        (fmapMaybeM  addTickLHsExprAlways by)
+       (fmapEitherM addTickLHsExprAlways (addTickSyntaxExpr hpcSrcSpan) using)
+
+addTickStmt isGuard stmt@(RecStmt {})
+  = do { stmts' <- addTickLStmts isGuard (recS_stmts stmt)
+       ; ret'   <- addTickSyntaxExpr hpcSrcSpan (recS_ret_fn stmt)
+       ; mfix'  <- addTickSyntaxExpr hpcSrcSpan (recS_mfix_fn stmt)
+       ; bind'  <- addTickSyntaxExpr hpcSrcSpan (recS_bind_fn stmt)
+       ; dicts' <- addTickEvBinds (recS_dicts stmt)
+       ; return (stmt { recS_stmts = stmts', recS_ret_fn = ret'
+                      , recS_mfix_fn = mfix', recS_bind_fn = bind'
+                      , recS_dicts = dicts' }) }
 
 addTick :: Maybe (Bool -> BoxLabel) -> LHsExpr Id -> TM (LHsExpr Id)
 addTick isGuard e | Just fn <- isGuard = addBinTickLHsExpr fn e
@@ -498,7 +508,7 @@ addTickHsIPBinds :: HsIPBinds Id -> TM (HsIPBinds Id)
 addTickHsIPBinds (IPBinds ipbinds dictbinds) =
        liftM2 IPBinds
                (mapM (liftL (addTickIPBind)) ipbinds)
-               (addTickDictBinds dictbinds)
+               (return dictbinds)
 
 addTickIPBind :: IPBind Id -> TM (IPBind Id)
 addTickIPBind (IPBind nm e) =
@@ -526,8 +536,8 @@ addTickHsCmdTop (HsCmdTop cmd tys ty syntaxtable) =
 addTickLHsCmd ::  LHsCmd Id -> TM (LHsCmd Id)
 addTickLHsCmd x = addTickLHsExpr x
 
-addTickDictBinds :: DictBinds Id -> TM (DictBinds Id)
-addTickDictBinds x = addTickLHsBinds x
+addTickEvBinds :: TcEvBinds -> TM TcEvBinds
+addTickEvBinds x = return x   -- No coverage testing for dictionary binding
 
 addTickHsRecordBinds :: HsRecordBinds Id -> TM (HsRecordBinds Id)
 addTickHsRecordBinds (HsRecFields fields dd) 
@@ -565,7 +575,7 @@ data TickTransState = TT { tickBoxCount:: Int
 data TickTransEnv = TTE { fileName      :: FastString
                        , declPath     :: [String]
                         , inScope      :: VarSet
-                       , blackList   :: FiniteMap SrcSpan ()
+                       , blackList   :: Map SrcSpan ()
                        }
 
 --     deriving Show
@@ -649,7 +659,7 @@ bindLocals new_ids (TM m)
 
 isBlackListed :: SrcSpan -> TM Bool
 isBlackListed pos = TM $ \ env st -> 
-             case lookupFM (blackList env) pos of
+             case Map.lookup pos (blackList env) of
                Nothing -> (False,noFVs,st)
                Just () -> (True,noFVs,st)
 
@@ -688,29 +698,28 @@ allocATickBox boxLabel pos fvs | isGoodSrcSpan' pos =
      )
 allocATickBox _boxLabel _pos _fvs = return Nothing
 
-allocBinTickBox :: (Bool -> BoxLabel) -> LHsExpr Id -> TM (LHsExpr Id)
-allocBinTickBox boxLabel (L pos e) | isGoodSrcSpan' pos = TM $ \ _env st ->
+allocBinTickBox :: (Bool -> BoxLabel) -> SrcSpan -> TM (HsExpr Id)
+                -> TM (LHsExpr Id)
+allocBinTickBox boxLabel pos m
+ | not opt_Hpc = allocTickBox (ExpBox False) pos m
+ | isGoodSrcSpan' pos =
+ do
+ e <- m
+ TM $ \ _env st ->
   let meT = (pos,[],boxLabel True)
       meF = (pos,[],boxLabel False)
       meE = (pos,[],ExpBox False)
       c = tickBoxCount st
       mes = mixEntries st
   in 
-     if opt_Hpc 
-        then ( L pos $ HsTick c [] $ L pos $ HsBinTick (c+1) (c+2) (L pos e)
+             ( L pos $ HsTick c [] $ L pos $ HsBinTick (c+1) (c+2) (L pos e)
            -- notice that F and T are reversed,
            -- because we are building the list in
            -- reverse...
              , noFVs
              , st {tickBoxCount=c+3 , mixEntries=meF:meT:meE:mes}
              )
-        else
-             ( L pos $ HsTick c [] $ L pos e
-             , noFVs
-             , st {tickBoxCount=c+1,mixEntries=meE:mes}
-             )
-
-allocBinTickBox _boxLabel e = return e
+allocBinTickBox _boxLabel pos m = do e <- m; return (L pos e)
 
 isGoodSrcSpan' :: SrcSpan -> Bool
 isGoodSrcSpan' pos
@@ -729,9 +738,9 @@ mkHpcPos pos
    start = srcSpanStart pos
    end   = srcSpanEnd pos
    hpcPos = toHpcPos ( srcLocLine start
-                    , srcLocCol start + 1
+                    , srcLocCol start
                     , srcLocLine end
-                    , srcLocCol end
+                    , srcLocCol end - 1
                     )
 
 hpcSrcSpan :: SrcSpan