[project @ 2004-08-16 09:53:47 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcRnMonad.lhs
index 8f8a6df..e2611e3 100644 (file)
@@ -10,7 +10,6 @@ module TcRnMonad(
 import TcRnTypes       -- Re-export all
 import IOEnv           -- Re-export all
 
-import HsSyn           ( MonoBinds(..) )
 import HscTypes                ( HscEnv(..), ModGuts(..), ModIface(..),
                          TyThing, Dependencies(..), TypeEnv, emptyTypeEnv,
                          ExternalPackageState(..), HomePackageTable,
@@ -28,8 +27,9 @@ import InstEnv                ( InstEnv, emptyInstEnv, extendInstEnv )
 import VarSet          ( emptyVarSet )
 import VarEnv          ( TidyEnv, emptyTidyEnv )
 import ErrUtils                ( Message, Messages, emptyMessages, errorsFound, 
-                         addShortErrLocLine, addShortWarnLocLine, printErrorsAndWarnings )
-import SrcLoc          ( SrcLoc, mkGeneralSrcLoc )
+                         mkErrMsg, mkWarnMsg, printErrorsAndWarnings,
+                         mkLocMessage, mkLongErrMsg )
+import SrcLoc          ( mkGeneralSrcSpan, isGoodSrcSpan, SrcSpan, Located(..) )
 import NameEnv         ( emptyNameEnv )
 import NameSet         ( emptyDUs, emptyNameSet )
 import OccName         ( emptyOccEnv )
@@ -65,7 +65,7 @@ ioToTcRn = ioToIOEnv
 initTc :: HscEnv
        -> Module 
        -> TcM r
-       -> IO (Maybe r)
+       -> IO (Messages, Maybe r)
                -- Nothing => error thrown by the thing inside
                -- (error messages should have been printed already)
 
@@ -74,6 +74,7 @@ initTc hsc_env mod do_this
        tvs_var      <- newIORef emptyVarSet ;
        type_env_var <- newIORef emptyNameEnv ;
        dfuns_var    <- newIORef emptyNameSet ;
+       th_var       <- newIORef False ;
 
        let {
             gbl_env = TcGblEnv {
@@ -85,10 +86,11 @@ initTc hsc_env mod do_this
                tcg_type_env_var = type_env_var,
                tcg_inst_env  = mkImpInstEnv hsc_env,
                tcg_inst_uses = dfuns_var,
-               tcg_exports  = [],
+               tcg_th_used   = th_var,
+               tcg_exports  = emptyNameSet,
                tcg_imports  = init_imports,
                tcg_dus      = emptyDUs,
-               tcg_binds    = EmptyMonoBinds,
+               tcg_binds    = emptyBag,
                tcg_deprecs  = NoDeprecs,
                tcg_insts    = [],
                tcg_rules    = [],
@@ -97,7 +99,7 @@ initTc hsc_env mod do_this
             } ;
             lcl_env = TcLclEnv {
                tcl_errs       = errs_var,
-               tcl_loc        = mkGeneralSrcLoc FSLIT("Top level of module"),
+               tcl_loc        = mkGeneralSrcSpan FSLIT("Top level"),
                tcl_ctxt       = [],
                tcl_rdr        = emptyLocalRdrEnv,
                tcl_th_ctxt    = topStage,
@@ -115,15 +117,14 @@ initTc hsc_env mod do_this
                                    Right res -> return (Just res)
                                    Left _    -> return Nothing } ;
 
-       -- Print any error messages
+       -- Collect any error messages
        msgs <- readIORef errs_var ;
-       printErrorsAndWarnings msgs ;
 
        let { dflags = hsc_dflags hsc_env
            ; final_res | errorsFound dflags msgs = Nothing
                        | otherwise               = maybe_res } ;
 
-       return final_res
+       return (msgs, final_res)
     }
   where
     init_imports = emptyImportAvails { imp_qual = unitModuleEnv mod emptyAvailEnv }
@@ -132,6 +133,16 @@ initTc hsc_env mod do_this
        -- list, and there are no bindings in M, we don't bleat 
        -- "unknown module M".
 
+initTcPrintErrors
+       :: HscEnv
+       -> Module 
+       -> TcM r
+       -> IO (Maybe r)
+initTcPrintErrors env mod todo = do
+  (msgs, res) <- initTc env mod todo
+  printErrorsAndWarnings msgs
+  return res
+
 mkImpInstEnv :: HscEnv -> InstEnv
 -- At the moment we (wrongly) build an instance environment from all the
 -- home-package modules we have already compiled.
@@ -245,24 +256,36 @@ getEpsVar = do { env <- getTopEnv; return (hsc_EPS env) }
 getEps :: TcRnIf gbl lcl ExternalPackageState
 getEps = do { env <- getTopEnv; readMutVar (hsc_EPS env) }
 
-setEps :: ExternalPackageState -> TcRnIf gbl lcl ()
-setEps eps = do { env <- getTopEnv; writeMutVar (hsc_EPS env) eps }
+-- Updating the EPS.  This should be an atomic operation.
+-- Note the delicate 'seq' which forces the EPS before putting it in the
+-- variable.  Otherwise what happens is that we get
+--     write eps_var (....(unsafeRead eps_var)....)
+-- and if the .... is strict, that's obviously bottom.  By forcing it beforehand
+-- we make the unsafeRead happen before we update the variable.
 
 updateEps :: (ExternalPackageState -> (ExternalPackageState, a))
          -> TcRnIf gbl lcl a
-updateEps upd_fn = do  { eps_var <- getEpsVar
+updateEps upd_fn = do  { traceIf (text "updating EPS")
+                       ; eps_var <- getEpsVar
                        ; eps <- readMutVar eps_var
                        ; let { (eps', val) = upd_fn eps }
-                       ; writeMutVar eps_var eps'
+                       ; seq eps' (writeMutVar eps_var eps')
                        ; return val }
 
 updateEps_ :: (ExternalPackageState -> ExternalPackageState)
           -> TcRnIf gbl lcl ()
-updateEps_ upd_fn = do { eps_var <- getEpsVar
-                       ; updMutVar eps_var upd_fn }
+updateEps_ upd_fn = do { traceIf (text "updating EPS_")
+                       ; eps_var <- getEpsVar
+                       ; eps <- readMutVar eps_var
+                       ; let { eps' = upd_fn eps }
+                       ; seq eps' (writeMutVar eps_var eps') }
 
 getHpt :: TcRnIf gbl lcl HomePackageTable
 getHpt = do { env <- getTopEnv; return (hsc_HPT env) }
+
+getEpsAndHpt :: TcRnIf gbl lcl (ExternalPackageState, HomePackageTable)
+getEpsAndHpt = do { env <- getTopEnv; eps <- readMutVar (hsc_EPS env)
+                 ; return (eps, hsc_HPT env) }
 \end{code}
 
 %************************************************************************
@@ -310,7 +333,12 @@ dumpOptIf flag doc = ifOptM flag $
                     ioToIOEnv (printForUser stderr alwaysQualify doc)
 
 dumpOptTcRn :: DynFlag -> SDoc -> TcRn ()
-dumpOptTcRn flag doc = ifOptM flag (dumpTcRn doc)
+dumpOptTcRn flag doc = ifOptM flag $ do
+                       { ctxt <- getErrCtxt
+                       ; loc  <- getSrcSpanM
+                       ; ctxt_msgs <- do_ctxt emptyTidyEnv ctxt 
+                       ; let real_doc = mkLocMessage loc (vcat (doc : ctxt_to_use ctxt_msgs))
+                       ; dumpTcRn real_doc }
 
 dumpTcRn :: SDoc -> TcRn ()
 dumpTcRn doc = do { rdr_env <- getGlobalRdrEnv ;
@@ -353,12 +381,32 @@ getDefaultTys = do { env <- getGblEnv; return (tcg_default env) }
 %************************************************************************
 
 \begin{code}
-getSrcLocM :: TcRn SrcLoc
+getSrcSpanM :: TcRn SrcSpan
        -- Avoid clash with Name.getSrcLoc
-getSrcLocM = do { env <- getLclEnv; return (tcl_loc env) }
-
-addSrcLoc :: SrcLoc -> TcRn a -> TcRn a
-addSrcLoc loc = updLclEnv (\env -> env { tcl_loc = loc })
+getSrcSpanM = do { env <- getLclEnv; return (tcl_loc env) }
+
+addSrcSpan :: SrcSpan -> TcRn a -> TcRn a
+addSrcSpan loc thing_inside
+  | isGoodSrcSpan loc = updLclEnv (\env -> env { tcl_loc = loc }) thing_inside
+  | otherwise        = thing_inside    -- Don't overwrite useful info with useless
+
+addLocM :: (a -> TcM b) -> Located a -> TcM b
+addLocM fn (L loc a) = addSrcSpan loc $ fn a
+
+wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)
+wrapLocM fn (L loc a) = addSrcSpan loc $ do b <- fn a; return (L loc b)
+
+wrapLocFstM :: (a -> TcM (b,c)) -> Located a -> TcM (Located b, c)
+wrapLocFstM fn (L loc a) =
+  addSrcSpan loc $ do
+    (b,c) <- fn a
+    return (L loc b, c)
+
+wrapLocSndM :: (a -> TcM (b,c)) -> Located a -> TcM (b, Located c)
+wrapLocSndM fn (L loc a) =
+  addSrcSpan loc $ do
+    (b,c) <- fn a
+    return (b, L loc c)
 \end{code}
 
 
@@ -370,33 +418,47 @@ setErrsVar :: TcRef Messages -> TcRn a -> TcRn a
 setErrsVar v = updLclEnv (\ env -> env { tcl_errs =  v })
 
 addErr :: Message -> TcRn ()
-addErr msg = do { loc <- getSrcLocM ; addErrAt loc msg }
+addErr msg = do { loc <- getSrcSpanM ; addErrAt loc msg }
+
+addLocErr :: Located e -> (e -> Message) -> TcRn ()
+addLocErr (L loc e) fn = addErrAt loc (fn e)
 
-addErrAt :: SrcLoc -> Message -> TcRn ()
-addErrAt loc msg
+addErrAt :: SrcSpan -> Message -> TcRn ()
+addErrAt loc msg = addLongErrAt loc msg empty
+
+addLongErrAt :: SrcSpan -> Message -> Message -> TcRn ()
+addLongErrAt loc msg extra
  = do {  errs_var <- getErrsVar ;
         rdr_env <- getGlobalRdrEnv ;
-        let { err = addShortErrLocLine loc (unQualInScope rdr_env) msg } ;
+        let { err = mkLongErrMsg loc (unQualInScope rdr_env) msg extra } ;
         (warns, errs) <- readMutVar errs_var ;
         writeMutVar errs_var (warns, errs `snocBag` err) }
 
-addErrs :: [(SrcLoc,Message)] -> TcRn ()
+addErrs :: [(SrcSpan,Message)] -> TcRn ()
 addErrs msgs = mappM_ add msgs
             where
               add (loc,msg) = addErrAt loc msg
 
 addReport :: Message -> TcRn ()
-addReport msg
+addReport msg = do loc <- getSrcSpanM; addReportAt loc msg
+
+addReportAt :: SrcSpan -> Message -> TcRn ()
+addReportAt loc msg
   = do { errs_var <- getErrsVar ;
-        loc <- getSrcLocM ;
         rdr_env <- getGlobalRdrEnv ;
-        let { warn = addShortWarnLocLine loc (unQualInScope rdr_env) msg } ;
+        let { warn = mkWarnMsg loc (unQualInScope rdr_env) msg } ;
         (warns, errs) <- readMutVar errs_var ;
         writeMutVar errs_var (warns `snocBag` warn, errs) }
 
 addWarn :: Message -> TcRn ()
 addWarn msg = addReport (ptext SLIT("Warning:") <+> msg)
 
+addWarnAt :: SrcSpan -> Message -> TcRn ()
+addWarnAt loc msg = addReportAt loc (ptext SLIT("Warning:") <+> msg)
+
+addLocWarn :: Located e -> (e -> Message) -> TcRn ()
+addLocWarn (L loc e) fn = addReportAt loc (fn e)
+
 checkErr :: Bool -> Message -> TcRn ()
 -- Add the error if the bool is False
 checkErr ok msg = checkM ok (addErr msg)
@@ -554,14 +616,14 @@ updCtxt upd = updLclEnv (\ env@(TcLclEnv { tcl_ctxt = ctxt }) ->
 
 getInstLoc :: InstOrigin -> TcM InstLoc
 getInstLoc origin
-  = do { loc <- getSrcLocM ; env <- getLclEnv ;
+  = do { loc <- getSrcSpanM ; env <- getLclEnv ;
         return (InstLoc origin loc (tcl_ctxt env)) }
 
 addInstCtxt :: InstLoc -> TcM a -> TcM a
--- Add the SrcLoc and context from the first Inst in the list
+-- Add the SrcSpan and context from the first Inst in the list
 --     (they all have similar locations)
 addInstCtxt (InstLoc _ src_loc ctxt) thing_inside
-  = addSrcLoc src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
+  = addSrcSpan src_loc (updCtxt (\ old_ctxt -> ctxt) thing_inside)
 \end{code}
 
     The addErrTc functions add an error message, but do not cause failure.
@@ -578,7 +640,7 @@ addErrsTc err_msgs = mappM_ addErrTc err_msgs
 addErrTcM :: (TidyEnv, Message) -> TcM ()
 addErrTcM (tidy_env, err_msg)
   = do { ctxt <- getErrCtxt ;
-        loc  <- getSrcLocM ;
+        loc  <- getSrcSpanM ;
         add_err_tcm tidy_env err_msg loc ctxt }
 \end{code}
 
@@ -618,7 +680,7 @@ warnTc warn_if_true warn_msg
 \begin{code}
 add_err_tcm tidy_env err_msg loc ctxt
  = do { ctxt_msgs <- do_ctxt tidy_env ctxt ;
-       addErrAt loc (vcat (err_msg : ctxt_to_use ctxt_msgs)) }
+       addLongErrAt loc err_msg (vcat (ctxt_to_use ctxt_msgs)) }
 
 do_ctxt tidy_env []
  = return []
@@ -687,6 +749,9 @@ setLclTypeEnv lcl_env thing_inside
 %************************************************************************
 
 \begin{code}
+recordThUse :: TcM ()
+recordThUse = do { env <- getGblEnv; writeMutVar (tcg_th_used env) True }
+
 getStage :: TcM ThStage
 getStage = do { env <- getLclEnv; return (tcl_th_ctxt env) }
 
@@ -748,8 +813,7 @@ initIfaceTcRn :: IfG a -> TcRn a
 initIfaceTcRn thing_inside
   = do  { tcg_env <- getGblEnv 
        ; let { if_env = IfGblEnv { 
-                       if_rec_types = Just (tcg_mod tcg_env, get_type_env),
-                       if_is_boot   = imp_dep_mods (tcg_imports tcg_env) }
+                       if_rec_types = Just (tcg_mod tcg_env, get_type_env) }
              ; get_type_env = readMutVar (tcg_type_env_var tcg_env) }
        ; setEnvs (if_env, ()) thing_inside }
 
@@ -758,8 +822,7 @@ initIfaceExtCore thing_inside
   = do  { tcg_env <- getGblEnv 
        ; let { mod = tcg_mod tcg_env
              ; if_env = IfGblEnv { 
-                       if_rec_types = Just (mod, return (tcg_type_env tcg_env)), 
-                       if_is_boot   = imp_dep_mods (tcg_imports tcg_env) }
+                       if_rec_types = Just (mod, return (tcg_type_env tcg_env)) }
              ; if_lenv = IfLclEnv { if_mod     = moduleName mod,
                                     if_tv_env  = emptyOccEnv,
                                     if_id_env  = emptyOccEnv }
@@ -770,8 +833,7 @@ initIfaceCheck :: HscEnv -> IfG a -> IO a
 -- Used when checking the up-to-date-ness of the old Iface
 -- Initialise the environment with no useful info at all
 initIfaceCheck hsc_env do_this
- = do  { let { gbl_env = IfGblEnv { if_is_boot   = emptyModuleEnv,
-                                    if_rec_types = Nothing } ;
+ = do  { let { gbl_env = IfGblEnv { if_rec_types = Nothing } ;
           }
        ; initTcRnIf 'i' hsc_env gbl_env () do_this
     }
@@ -782,8 +844,7 @@ initIfaceTc :: HscEnv -> ModIface
 -- No type envt from the current module, but we do know the module dependencies
 initIfaceTc hsc_env iface do_this
  = do  { tc_env_var <- newIORef emptyTypeEnv
-       ; let { gbl_env = IfGblEnv { if_is_boot   = mkModDeps (dep_mods (mi_deps iface)),
-                                    if_rec_types = Just (mod, readMutVar tc_env_var) } ;
+       ; let { gbl_env = IfGblEnv { if_rec_types = Just (mod, readMutVar tc_env_var) } ;
              ; if_lenv = IfLclEnv { if_mod     = moduleName mod,
                                     if_tv_env  = emptyOccEnv,
                                     if_id_env  = emptyOccEnv }
@@ -798,13 +859,8 @@ initIfaceRules :: HscEnv -> ModGuts -> IfG a -> IO a
 -- We have available the type envt of the module being compiled, and we must use it
 initIfaceRules hsc_env guts do_this
  = do  { let {
-            is_boot = mkModDeps (dep_mods (mg_deps guts))
-                       -- Urgh!  But we do somehow need to get the info
-                       -- on whether (for this particular compilation) we should
-                       -- import a hi-boot file or not.
-          ; type_info = (mg_module guts, return (mg_types guts))
-          ; gbl_env = IfGblEnv { if_is_boot   = is_boot,
-                                 if_rec_types = Just type_info } ;
+            type_info = (mg_module guts, return (mg_types guts))
+          ; gbl_env = IfGblEnv { if_rec_types = Just type_info } ;
           }
 
        -- Run the thing; any exceptions just bubble out from here