[project @ 2003-05-27 14:15:40 by simonmar]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreLint.lhs
index 03d4945..7470294 100644 (file)
@@ -7,15 +7,12 @@
 module CoreLint (
        lintCoreBindings,
        lintUnfolding, 
-       showPass, endPass, endPassWithRules
+       showPass, endPass
     ) where
 
 #include "HsVersions.h"
 
-import IO              ( hPutStr, hPutStrLn, stdout )
-
 import CoreSyn
-import Rules            ( RuleBase, pprRuleBase )
 import CoreFVs         ( idFreeVars )
 import CoreUtils       ( findDefault, exprOkForSpeculation, coreBindsSize, mkPiType )
 
@@ -27,9 +24,8 @@ import VarSet
 import Subst           ( substTyWith )
 import Name            ( getSrcLoc )
 import PprCore
-import ErrUtils                ( doIfSet, dumpIfSet_core, ghcExit, Message, showPass,
-                         ErrMsg, addErrLocHdrLine, pprBagOfErrors,
-                          WarnMsg, pprBagOfWarnings)
+import ErrUtils                ( dumpIfSet_core, ghcExit, Message, showPass,
+                         addErrLocHdrLine )
 import SrcLoc          ( SrcLoc, noSrcLoc )
 import Type            ( Type, tyVarsOfType, eqType,
                          splitFunTy_maybe, mkTyVarTy,
@@ -44,51 +40,39 @@ import CmdLineOpts
 import Maybe
 import Outputable
 
+import IO              ( hPutStrLn, stderr )
+
 infixr 9 `thenL`, `seqL`
 \end{code}
 
 %************************************************************************
 %*                                                                     *
-\subsection{Start and end pass}
+\subsection{End pass}
 %*                                                                     *
 %************************************************************************
 
-@beginPass@ and @endPass@ don't really belong here, but it makes a convenient
+@showPass@ and @endPass@ don't really belong here, but it makes a convenient
 place for them.  They print out stuff before and after core passes,
 and do Core Lint when necessary.
 
 \begin{code}
 endPass :: DynFlags -> String -> DynFlag -> [CoreBind] -> IO [CoreBind]
 endPass dflags pass_name dump_flag binds
-  = do  
-        (binds, _) <- endPassWithRules dflags pass_name dump_flag binds Nothing
-        return binds
-
-endPassWithRules :: DynFlags -> String -> DynFlag -> [CoreBind] 
-                -> Maybe RuleBase
-                 -> IO ([CoreBind], Maybe RuleBase)
-endPassWithRules dflags pass_name dump_flag binds rules
   = do 
-        -- ToDo: force the rules?
-
        -- Report result size if required
        -- This has the side effect of forcing the intermediate to be evaluated
        if verbosity dflags >= 2 then
-          hPutStrLn stdout ("    Result size = " ++ show (coreBindsSize binds))
+          hPutStrLn stderr ("    Result size = " ++ show (coreBindsSize binds))
         else
           return ()
 
        -- Report verbosely, if required
-       dumpIfSet_core dflags dump_flag pass_name
-                 (pprCoreBindings binds $$ case rules of
-                                              Nothing -> empty
-                                              Just rb -> pprRuleBase rb)
+       dumpIfSet_core dflags dump_flag pass_name (pprCoreBindings binds)
 
        -- Type check
        lintCoreBindings dflags pass_name binds
-        -- ToDo: lint the rules
 
-       return (binds, rules)
+       return binds
 \end{code}
 
 
@@ -131,13 +115,9 @@ lintCoreBindings dflags whoDunnit binds
 
 lintCoreBindings dflags whoDunnit binds
   = case (initL (lint_binds binds)) of
-      (Nothing, Nothing)       -> done_lint
-
-      (Nothing, Just warnings) -> printDump (warn warnings) >>
-                                  done_lint
-
-      (Just bad_news, warns)   -> printDump (display bad_news warns)   >>
-                                 ghcExit 1
+      Nothing       -> showPass dflags ("Core Linted result of " ++ whoDunnit)
+      Just bad_news -> printDump (display bad_news)    >>
+                      ghcExit 1
   where
        -- Put all the top-level binders in scope at the start
        -- This is because transformation rules can bring something
@@ -149,24 +129,9 @@ lintCoreBindings dflags whoDunnit binds
                                  returnL ()
     lint_bind (NonRec bndr rhs) = lintSingleBinding NonRecursive (bndr,rhs)
 
-    done_lint = doIfSet (verbosity dflags >= 2)
-                       (hPutStr stdout ("*** Core Linted result of " ++ whoDunnit ++ "\n"))
-    warn warnings
-      = vcat [
-                text ("*** Core Lint Warnings: in result of " ++ whoDunnit ++ " ***"),
-                warnings,
-                offender
-        ]
-
-    display bad_news warns
-      = vcat [
-               text ("*** Core Lint Errors: in result of " ++ whoDunnit ++ " ***"),
+    display bad_news
+      = vcat [  text ("*** Core Lint Errors: in result of " ++ whoDunnit ++ " ***"),
                bad_news,
-                maybe offender warn warns  -- either offender or warnings (with offender)
-        ]
-
-    offender
-      = vcat [
                ptext SLIT("*** Offending Program ***"),
                pprCoreBindings binds,
                ptext SLIT("*** End of Offense ***")
@@ -183,17 +148,12 @@ We use this to check all unfoldings that come in from interfaces
 (it is very painful to catch errors otherwise):
 
 \begin{code}
-lintUnfolding :: DynFlags 
-             -> SrcLoc
+lintUnfolding :: SrcLoc
              -> [Var]          -- Treat these as in scope
              -> CoreExpr
-             -> (Maybe Message, Maybe Message)         -- (Nothing,_) => OK
-
-lintUnfolding dflags locn vars expr
-  | not (dopt Opt_DoCoreLinting dflags)
-  = (Nothing, Nothing)
+             -> Maybe Message  -- Nothing => OK
 
-  | otherwise
+lintUnfolding locn vars expr
   = initL (addLoc (ImportedUnfolding locn) $
           addInScopeVars vars             $
           lintCoreExpr expr)
@@ -451,6 +411,7 @@ lintCoreAlt scrut_ty alt@(DataAlt con, args, rhs)
        -- Scrutinee type must be a tycon applicn; checked by caller
        -- This code is remarkably compact considering what it does!
        -- NB: args must be in scope here so that the lintCoreArgs line works.
+       -- NB: relies on existential type args coming *after* ordinary type args
     case splitTyConApp scrut_ty of { (tycon, tycon_arg_tys) ->
        lintTyApps (dataConRepType con) tycon_arg_tys   `thenL` \ con_type ->
        lintCoreArgs con_type (map mk_arg args)         `thenL` \ con_result_ty ->
@@ -494,9 +455,8 @@ lintTy ty = mapL checkIdInScope (varSetElems (tyVarsOfType ty))     `seqL`
 \begin{code}
 type LintM a = [LintLocInfo]   -- Locations
            -> IdSet            -- Local vars in scope
-           -> Bag ErrMsg       -- Error messages so far
-            -> Bag WarnMsg      -- Warning messages so far
-           -> (Maybe a, Bag ErrMsg, Bag WarnMsg)  -- Result and error/warning messages (if any)
+           -> Bag Message      -- Error messages so far
+           -> (Maybe a, Bag Message)  -- Result and error messages (if any)
 
 data LintLocInfo
   = RhsOf Id           -- The variable bound
@@ -508,31 +468,28 @@ data LintLocInfo
 \end{code}
 
 \begin{code}
-initL :: LintM a -> (Maybe Message {- errors -}, Maybe Message {- warnings -})
+initL :: LintM a -> Maybe Message {- errors -}
 initL m
-  = case m [] emptyVarSet emptyBag emptyBag of
-      (_, errs, warns) -> (ifNonEmptyBag errs  pprBagOfErrors,
-                           ifNonEmptyBag warns pprBagOfWarnings)
-  where
-    ifNonEmptyBag bag f | isEmptyBag bag = Nothing
-                        | otherwise      = Just (f bag)
+  = case m [] emptyVarSet emptyBag of
+      (_, errs) | isEmptyBag errs -> Nothing
+               | otherwise       -> Just (vcat (punctuate (text "") (bagToList errs)))
 
 returnL :: a -> LintM a
-returnL r loc scope errs warns = (Just r, errs, warns)
+returnL r loc scope errs = (Just r, errs)
 
 nopL :: LintM a
-nopL loc scope errs warns = (Nothing, errs, warns)
+nopL loc scope errs = (Nothing, errs)
 
 thenL :: LintM a -> (a -> LintM b) -> LintM b
-thenL m k loc scope errs warns
-  = case m loc scope errs warns of
-      (Just r, errs', warns')  -> k r loc scope errs' warns'
-      (Nothing, errs', warns') -> (Nothing, errs', warns')
+thenL m k loc scope errs
+  = case m loc scope errs of
+      (Just r, errs')  -> k r loc scope errs'
+      (Nothing, errs') -> (Nothing, errs')
 
 seqL :: LintM a -> LintM b -> LintM b
-seqL m k loc scope errs warns
-  = case m loc scope errs warns of
-      (_, errs', warns') -> k loc scope errs' warns'
+seqL m k loc scope errs
+  = case m loc scope errs of
+      (_, errs') -> k loc scope errs'
 
 mapL :: (a -> LintM b) -> [a] -> LintM [b]
 mapL f [] = returnL []
@@ -548,12 +505,11 @@ checkL True  msg = nopL
 checkL False msg = addErrL msg
 
 addErrL :: Message -> LintM a
-addErrL msg loc scope errs warns = (Nothing, addErr errs msg loc, warns)
+addErrL msg loc scope errs = (Nothing, addErr errs msg loc)
 
-addErr :: Bag ErrMsg -> Message -> [LintLocInfo] -> Bag ErrMsg
--- errors or warnings, actually... they're the same type.
+addErr :: Bag Message -> Message -> [LintLocInfo] -> Bag Message
 addErr errs_so_far msg locs
-  = ASSERT( not (null locs) )
+  = ASSERT( notNull locs )
     errs_so_far `snocBag` mk_msg msg
   where
    (loc, cxt1) = dumpLoc (head locs)
@@ -564,12 +520,12 @@ addErr errs_so_far msg locs
    mk_msg msg = addErrLocHdrLine loc context msg
 
 addLoc :: LintLocInfo -> LintM a -> LintM a
-addLoc extra_loc m loc scope errs warns
-  = m (extra_loc:loc) scope errs warns
+addLoc extra_loc m loc scope errs
+  = m (extra_loc:loc) scope errs
 
 addInScopeVars :: [Var] -> LintM a -> LintM a
-addInScopeVars ids m loc scope errs warns
-  = m loc (scope `unionVarSet` mkVarSet ids) errs warns
+addInScopeVars ids m loc scope errs
+  = m loc (scope `unionVarSet` mkVarSet ids) errs
 \end{code}
 
 \begin{code}
@@ -585,11 +541,11 @@ checkBndrIdInScope binder id
           ppr binder
 
 checkInScope :: SDoc -> Var -> LintM ()
-checkInScope loc_msg var loc scope errs warns
+checkInScope loc_msg var loc scope errs
   |  mustHaveLocalBinding var && not (var `elemVarSet` scope)
-  = (Nothing, addErr errs (hsep [ppr var, loc_msg]) loc, warns)
+  = (Nothing, addErr errs (hsep [ppr var, loc_msg]) loc)
   | otherwise
-  = nopL loc scope errs warns
+  = nopL loc scope errs
 
 checkTys :: Type -> Type -> Message -> LintM ()
 -- check ty2 is subtype of ty1 (ie, has same structure but usage