[project @ 2005-05-05 10:52:43 by ross]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcRnMonad.lhs
index 88a2e69..306a71b 100644 (file)
@@ -12,18 +12,17 @@ import IOEnv                -- Re-export all
 
 import HsSyn           ( emptyLHsBinds )
 import HscTypes                ( HscEnv(..), ModGuts(..), ModIface(..),
-                         TyThing, TypeEnv, emptyTypeEnv,
+                         TyThing, TypeEnv, emptyTypeEnv, HscSource(..), isHsBoot,
                          ExternalPackageState(..), HomePackageTable,
-                         ModDetails(..), HomeModInfo(..), 
-                         Deprecs(..), FixityEnv, FixItem,
-                         GhciMode, lookupType, unQualInScope )
-import Module          ( Module, unitModuleEnv, foldModuleEnv )
+                         Deprecs(..), FixityEnv, FixItem, 
+                         lookupType, unQualInScope )
+import Module          ( Module, unitModuleEnv )
 import RdrName         ( GlobalRdrEnv, emptyGlobalRdrEnv,      
                          LocalRdrEnv, emptyLocalRdrEnv )
 import Name            ( Name, isInternalName )
 import Type            ( Type )
 import NameEnv         ( extendNameEnvList )
-import InstEnv         ( InstEnv, emptyInstEnv, extendInstEnvList )
+import InstEnv         ( emptyInstEnv )
 
 import VarSet          ( emptyVarSet )
 import VarEnv          ( TidyEnv, emptyTidyEnv, emptyVarEnv )
@@ -38,7 +37,8 @@ import Bag            ( emptyBag )
 import Outputable
 import UniqSupply      ( UniqSupply, mkSplitUniqSupply, uniqFromSupply, splitUniqSupply )
 import Unique          ( Unique )
-import CmdLineOpts     ( DynFlags, DynFlag(..), dopt, opt_PprStyle_Debug, dopt_set )
+import DynFlags                ( DynFlags(..), DynFlag(..), dopt, dopt_set, GhcMode )
+import StaticFlags     ( opt_PprStyle_Debug )
 import Bag             ( snocBag, unionBags )
 import Panic           ( showException )
  
@@ -63,39 +63,44 @@ ioToTcRn = ioToIOEnv
 
 \begin{code}
 initTc :: HscEnv
+       -> HscSource
        -> Module 
        -> TcM r
        -> IO (Messages, Maybe r)
                -- Nothing => error thrown by the thing inside
                -- (error messages should have been printed already)
 
-initTc hsc_env mod do_this
+initTc hsc_env hsc_src mod do_this
  = do { errs_var     <- newIORef (emptyBag, emptyBag) ;
        tvs_var      <- newIORef emptyVarSet ;
        type_env_var <- newIORef emptyNameEnv ;
        dfuns_var    <- newIORef emptyNameSet ;
        keep_var     <- newIORef emptyNameSet ;
        th_var       <- newIORef False ;
+       dfun_n_var   <- newIORef 1 ;
 
        let {
             gbl_env = TcGblEnv {
                tcg_mod      = mod,
+               tcg_src      = hsc_src,
                tcg_rdr_env  = emptyGlobalRdrEnv,
                tcg_fix_env  = emptyNameEnv,
                tcg_default  = Nothing,
                tcg_type_env = emptyNameEnv,
                tcg_type_env_var = type_env_var,
-               tcg_inst_env  = mkHomePackageInstEnv hsc_env,
+               tcg_inst_env  = emptyInstEnv,
                tcg_inst_uses = dfuns_var,
                tcg_th_used   = th_var,
                tcg_exports  = emptyNameSet,
                tcg_imports  = init_imports,
                tcg_dus      = emptyDUs,
+               tcg_rn_decls = Nothing,
                tcg_binds    = emptyLHsBinds,
                tcg_deprecs  = NoDeprecs,
                tcg_insts    = [],
                tcg_rules    = [],
                tcg_fords    = [],
+               tcg_dfun_n   = dfun_n_var,
                tcg_keep     = keep_var
             } ;
             lcl_env = TcLclEnv {
@@ -104,7 +109,7 @@ initTc hsc_env mod do_this
                tcl_ctxt       = [],
                tcl_rdr        = emptyLocalRdrEnv,
                tcl_th_ctxt    = topStage,
-               tcl_arrow_ctxt = topArrowCtxt,
+               tcl_arrow_ctxt = NoArrowCtxt,
                tcl_env        = emptyNameEnv,
                tcl_tyvars     = tvs_var,
                tcl_lie        = panic "initTc:LIE",    -- LIE only valid inside a getLIE
@@ -135,26 +140,16 @@ initTc hsc_env mod do_this
        -- list, and there are no bindings in M, we don't bleat 
        -- "unknown module M".
 
-initTcPrintErrors
+initTcPrintErrors      -- Used from the interactive loop only
        :: HscEnv
        -> Module 
        -> TcM r
        -> IO (Maybe r)
 initTcPrintErrors env mod todo = do
-  (msgs, res) <- initTc env mod todo
+  (msgs, res) <- initTc env HsSrcFile mod todo
   printErrorsAndWarnings msgs
   return res
 
-mkHomePackageInstEnv :: HscEnv -> InstEnv
--- At the moment we (wrongly) build an instance environment from all the
--- home-package modules we have already compiled.
--- We should really only get instances from modules below us in the 
--- module import tree.
-mkHomePackageInstEnv (HscEnv {hsc_HPT = hpt})
-  = foldModuleEnv (add . md_insts . hm_details) emptyInstEnv hpt
-  where
-    add dfuns inst_env = extendInstEnvList inst_env dfuns
-
 -- mkImpTypeEnv makes the imported symbol table
 mkImpTypeEnv :: ExternalPackageState -> HomePackageTable
             -> Name -> Maybe TyThing
@@ -247,8 +242,8 @@ ifOptM :: DynFlag -> TcRnIf gbl lcl () -> TcRnIf gbl lcl () -- Do it flag is tru
 ifOptM flag thing_inside = do { b <- doptM flag; 
                                if b then thing_inside else return () }
 
-getGhciMode :: TcRnIf gbl lcl GhciMode
-getGhciMode = do { env <- getTopEnv; return (hsc_mode env) }
+getGhciMode :: TcRnIf gbl lcl GhcMode
+getGhciMode = do { env <- getTopEnv; return (ghcMode (hsc_dflags env)) }
 \end{code}
 
 \begin{code}
@@ -358,6 +353,9 @@ dumpTcRn doc = do { rdr_env <- getGlobalRdrEnv ;
 getModule :: TcRn Module
 getModule = do { env <- getGblEnv; return (tcg_mod env) }
 
+tcIsHsBoot :: TcRn Bool
+tcIsHsBoot = do { env <- getGblEnv; return (isHsBoot (tcg_src env)) }
+
 getGlobalRdrEnv :: TcRn GlobalRdrEnv
 getGlobalRdrEnv = do { env <- getGblEnv; return (tcg_rdr_env env) }
 
@@ -719,6 +717,13 @@ debugTc thing = return ()
 %************************************************************************
 
 \begin{code}
+nextDFunIndex :: TcM Int       -- Get the next dfun index
+nextDFunIndex = do { env <- getGblEnv
+                  ; let dfun_n_var = tcg_dfun_n env
+                  ; n <- readMutVar dfun_n_var
+                  ; writeMutVar dfun_n_var (n+1)
+                  ; return n }
+
 getLIEVar :: TcM (TcRef LIE)
 getLIEVar = do { env <- getLclEnv; return (tcl_lie env) }
 
@@ -789,32 +794,6 @@ setStage s = updLclEnv (\ env -> env { tcl_th_ctxt = s })
 
 %************************************************************************
 %*                                                                     *
-            Arrow context
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-popArrowBinders :: TcM a -> TcM a      -- Move to the left of a (-<); see comments in TcRnTypes
-popArrowBinders 
-  = updLclEnv (\ env -> env { tcl_arrow_ctxt = pop (tcl_arrow_ctxt env)  })
-  where
-    pop (ArrCtxt {proc_level = curr_lvl, proc_banned = banned})
-       = ASSERT( not (curr_lvl `elem` banned) )
-         ArrCtxt {proc_level = curr_lvl, proc_banned = curr_lvl : banned}
-
-getBannedProcLevels :: TcM [ProcLevel]
-  = do { env <- getLclEnv; return (proc_banned (tcl_arrow_ctxt env)) }
-
-incProcLevel :: TcM a -> TcM a
-incProcLevel 
-  = updLclEnv (\ env -> env { tcl_arrow_ctxt = inc (tcl_arrow_ctxt env) })
-  where
-    inc ctxt = ctxt { proc_level = proc_level ctxt + 1 }
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
             Stuff for the renamer's local env
 %*                                                                     *
 %************************************************************************
@@ -836,11 +815,16 @@ setLocalRdrEnv rdr_env thing_inside
 %************************************************************************
 
 \begin{code}
+mkIfLclEnv :: Module -> SDoc -> IfLclEnv
+mkIfLclEnv mod loc = IfLclEnv { if_mod     = mod,
+                               if_loc     = loc,
+                               if_tv_env  = emptyOccEnv,
+                               if_id_env  = emptyOccEnv }
+
 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) }
+       ; let { if_env = IfGblEnv { 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 }
 
@@ -848,11 +832,10 @@ initIfaceExtCore :: IfL a -> TcRn a
 initIfaceExtCore thing_inside
   = do  { tcg_env <- getGblEnv 
        ; let { mod = tcg_mod tcg_env
+             ; doc = ptext SLIT("External Core file for") <+> quotes (ppr mod)
              ; if_env = IfGblEnv { 
                        if_rec_types = Just (mod, return (tcg_type_env tcg_env)) }
-             ; if_lenv = IfLclEnv { if_mod     = mod,
-                                    if_tv_env  = emptyOccEnv,
-                                    if_id_env  = emptyOccEnv }
+             ; if_lenv = mkIfLclEnv mod doc
          }
        ; setEnvs (if_env, if_lenv) thing_inside }
 
@@ -860,26 +843,24 @@ 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_rec_types = Nothing } ;
-          }
+ = do  { let gbl_env = IfGblEnv { if_rec_types = Nothing }
        ; initTcRnIf 'i' hsc_env gbl_env () do_this
     }
 
-initIfaceTc :: HscEnv -> ModIface 
-           -> (TcRef TypeEnv -> IfL a) -> IO a
+initIfaceTc :: ModIface 
+           -> (TcRef TypeEnv -> IfL a) -> TcRnIf gbl lcl a
 -- Used when type-checking checking an up-to-date interface file
 -- 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
+initIfaceTc iface do_this
+ = do  { tc_env_var <- newMutVar emptyTypeEnv
        ; let { gbl_env = IfGblEnv { if_rec_types = Just (mod, readMutVar tc_env_var) } ;
-             ; if_lenv = IfLclEnv { if_mod     = mod,
-                                    if_tv_env  = emptyOccEnv,
-                                    if_id_env  = emptyOccEnv }
+             ; if_lenv = mkIfLclEnv mod doc
           }
-       ; initTcRnIf 'i' hsc_env gbl_env if_lenv (do_this tc_env_var)
+       ; setEnvs (gbl_env, if_lenv) (do_this tc_env_var)
     }
   where
     mod = mi_module iface
+    doc = ptext SLIT("The interface for") <+> quotes (ppr mod)
 
 initIfaceRules :: HscEnv -> ModGuts -> IfG a -> IO a
 -- Used when sucking in new Rules in SimplCore
@@ -894,13 +875,23 @@ initIfaceRules hsc_env guts do_this
        ; initTcRnIf 'i' hsc_env gbl_env () do_this
     }
 
-initIfaceLcl :: Module -> IfL a -> IfM lcl a
-initIfaceLcl mod thing_inside 
-  = setLclEnv (IfLclEnv { if_mod      = mod,
-                          if_tv_env  = emptyOccEnv,
-                          if_id_env  = emptyOccEnv })
-             thing_inside
+initIfaceLcl :: Module -> SDoc -> IfL a -> IfM lcl a
+initIfaceLcl mod loc_doc thing_inside 
+  = setLclEnv (mkIfLclEnv mod loc_doc) thing_inside
 
+getIfModule :: IfL Module
+getIfModule = do { env <- getLclEnv; return (if_mod env) }
+
+--------------------
+failIfM :: Message -> IfL a
+-- The Iface monad doesn't have a place to accumulate errors, so we
+-- just fall over fast if one happens; it "shouldnt happen".
+-- We use IfL here so that we can get context info out of the local env
+failIfM msg
+  = do         { env <- getLclEnv
+       ; let full_msg = if_loc env $$ nest 2 msg
+       ; ioToIOEnv (printErrs (full_msg defaultErrStyle))
+       ; failM }
 
 --------------------
 forkM_maybe :: SDoc -> IfL a -> IfL (Maybe a)