[project @ 2003-03-04 10:39:58 by simonmar]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcRnTypes.lhs
index 3cae143..69b0184 100644 (file)
@@ -11,7 +11,7 @@ module TcRnTypes(
        -- Non-standard operations
        runTcRn, fixM, tryM, ioToTcRn,
        newMutVar, readMutVar, writeMutVar,
-       getEnv, setEnv, updEnv, unsafeInterleaveM, 
+       getEnv, setEnv, updEnv, unsafeInterleaveM, zapEnv,
                
        -- The environment types
        Env(..), TopEnv(..), TcGblEnv(..), 
@@ -23,7 +23,7 @@ module TcRnTypes(
        ImportAvails(..), emptyImportAvails, plusImportAvails, 
        plusAvail, pruneAvails,  
        AvailEnv, emptyAvailEnv, unitAvailEnv, plusAvailEnv, 
-       mkAvailEnv, lookupAvailEnv, availEnvElts, addAvail,
+       mkAvailEnv, lookupAvailEnv, lookupAvailEnv_maybe, availEnvElts, addAvail,
        WhereFrom(..),
 
        -- Typechecker types
@@ -46,13 +46,14 @@ module TcRnTypes(
 
 import HsSyn           ( PendingSplice, HsOverLit, MonoBinds, RuleDecl, ForeignDecl )
 import RnHsSyn         ( RenamedHsExpr, RenamedPat, RenamedArithSeqInfo )
-import HscTypes                ( GhciMode, ExternalPackageState, HomePackageTable, NameCache,
-                         GlobalRdrEnv, LocalRdrEnv, FixityEnv, TypeEnv, TyThing, 
-                         Avails, GenAvailInfo(..), AvailInfo, availName,
-                         IsBootInterface, Deprecations )
+import HscTypes                ( GhciMode, ExternalPackageState, HomePackageTable, 
+                         NameCache, GlobalRdrEnv, LocalRdrEnv, FixityEnv,
+                         TypeEnv, TyThing, Avails, GenAvailInfo(..), AvailInfo,
+                          availName, IsBootInterface, Deprecations,
+                          ExternalPackageState(..), emptyExternalPackageState )
 import Packages                ( PackageName )
-import TcType          ( TcTyVarSet, TcType, TcTauType, TcThetaType, TcPredType, TcKind,
-                         tcCmpPred, tcCmpType, tcCmpTypes )
+import TcType          ( TcTyVarSet, TcType, TcTauType, TcThetaType, 
+                         TcPredType, TcKind, tcCmpPred, tcCmpType, tcCmpTypes )
 import InstEnv         ( DFunId, InstEnv )
 import Name            ( Name )
 import NameEnv
@@ -74,10 +75,11 @@ import Outputable
 import DATA_IOREF      ( IORef, newIORef, readIORef, writeIORef )
 import UNSAFE_IO       ( unsafeInterleaveIO )
 import FIX_IO          ( fixIO )
-import EXCEPTION       ( Exception )
+import EXCEPTION       ( Exception(..) )
+import IO              ( isUserError )
 import Maybe           ( mapMaybe )
 import ListSetOps      ( unionLists )
-import Panic           ( tryMost )
+import Panic           ( tryJust )
 \end{code}
 
 
@@ -157,7 +159,15 @@ Error recovery
 \begin{code}
 tryM :: TcRn m r -> TcRn m (Either Exception r)
 -- Reflect exception into TcRn monad
-tryM (TcRn thing) = TcRn (\ env -> tryMost (thing env))
+tryM (TcRn thing) = TcRn (\ env -> tryJust tc_errors (thing env))
+  where 
+#if __GLASGOW_HASKELL__ > 504 || __GLASGOW_HASKELL__ < 500
+       tc_errors e@(IOException ioe) | isUserError ioe = Just e
+#else
+       tc_errors e@(IOException _) | isUserError e = Just e
+#endif
+       tc_errors _other = Nothing
+       -- type checker failures show up as UserErrors only
 \end{code}
 
 Lazy interleave 
@@ -201,6 +211,47 @@ updEnv :: (Env m -> Env n) -> TcRn n a -> TcRn m a
 updEnv upd (TcRn m) = TcRn (\ env -> m (upd env))
 \end{code}
 
+\begin{code}
+zapEnv :: TcRn m a -> TcRn m a
+zapEnv act = TcRn $ \env@Env{ env_top=top, env_gbl=gbl, env_lcl=lcl } ->
+  case top of {
+   TopEnv{ 
+     top_mode    = mode,
+     top_dflags  = dflags,
+     top_hpt     = hpt,
+     top_eps     = eps,
+     top_us      = us
+    } -> do
+
+  eps_snap <- readIORef eps
+  ref <- newIORef $! emptyExternalPackageState{ eps_PTE = eps_PTE eps_snap }
+
+  let
+     top' = TopEnv {
+               top_mode   = mode,
+               top_dflags = dflags,
+               top_hpt    = hpt,
+               top_eps    = ref,
+               top_us     = us
+           }
+
+     type_env = tcg_type_env gbl
+     mod = tcg_mod gbl
+     gbl' = TcGblEnv {
+               tcg_mod = mod,
+               tcg_type_env = type_env
+           }
+
+     env' = Env {
+               env_top = top',
+               env_gbl = gbl',
+               env_lcl = lcl
+               -- leave the rest empty
+            }
+
+  case act of { TcRn f -> f env' }
+ }
+\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -235,6 +286,7 @@ data TopEnv -- Built once at top level then does not change
                -- PIT, ImportedModuleInfo
                -- DeclsMap, IfaceRules, IfaceInsts, InstGates
                -- TypeEnv, InstEnv, RuleBase
+               -- Mutable, because we demand-load declarations that extend the state
 
        top_hpt  :: HomePackageTable,
                -- The home package table that we've accumulated while 
@@ -273,15 +325,20 @@ data TcGblEnv
                -- (Ids defined in this module start in the local envt, 
                --  though they move to the global envt during zonking)
        
-               -- Cached things
-       tcg_ist :: Name -> Maybe TyThing,       -- Imported symbol table
-               -- Global type env: a combination of tcg_eps, tcg_hpt
-               --      (but *not* tcg_type_env; no deep reason)
-               -- When the PCS changes this must be refreshed, 
-               -- notably after running some compile-time code
-       
-       tcg_inst_env :: InstEnv,        -- Global instance env: a combination of 
+       tcg_inst_env :: TcRef InstEnv,  -- Global instance env: a combination of 
                                        --      tc_pcs, tc_hpt, *and* tc_insts
+               -- This field is mutable so that it can be updated inside a
+               -- Template Haskell splice, which might suck in some new
+               -- instance declarations.  This is a slightly different strategy
+               -- than for the type envt, where we look up first in tcg_type_env
+               -- and then in the mutable EPS, because the InstEnv for this module
+               -- is constructed (in principle at least) only from the modules
+               -- 'below' this one, so it's this-module-specific
+               --
+               -- On the other hand, a declaration quote [d| ... |] may introduce
+               -- some new instance declarations that we *don't* want to persist
+               -- outside the quote, so we tiresomely need to revert the InstEnv
+               -- after finishing the quote (see TcSplice.tcBracket)
 
                -- Now a bunch of things about this module that are simply 
                -- accumulated, but never consulted until the end.  
@@ -291,7 +348,10 @@ data TcGblEnv
        tcg_imports :: ImportAvails,            -- Information about what was imported 
                                                --    from where, including things bound
                                                --    in this module
-               -- The next fields are always fully zonked
+
+               -- The next fields accumulate the payload of the module
+               -- The binds, rules and foreign-decl fiels are collected
+               -- initially in un-zonked form and are finally zonked in tcRnSrcDecls
        tcg_binds   :: MonoBinds Id,            -- Value bindings in this module
        tcg_deprecs :: Deprecations,            -- ...Deprecations 
        tcg_insts   :: [DFunId],                -- ...Instances
@@ -355,7 +415,7 @@ topSpliceStage = Splice (topLevel - 1)      -- Stage for the body of a top-level spli
 
 
 impLevel, topLevel :: Level
-topLevel = 1   -- Things dedined at top level of this module
+topLevel = 1   -- Things defined at top level of this module
 impLevel = 0   -- Imported things; they can be used inside a top level splice
 --
 -- For example: 
@@ -455,10 +515,11 @@ emptyUsages = emptyNameSet
 
 ImportAvails summarises what was imported from where, irrespective
 of whether the imported htings are actually used or not
-It is used     * when porcessing the export list
+It is used     * when processing the export list
                * when constructing usage info for the inteface file
                * to identify the list of directly imported modules
                        for initialisation purposes
+               * when figuring out what things are really unused
 
 \begin{code}
 data ImportAvails 
@@ -588,7 +649,13 @@ unitAvailEnv a = unitNameEnv (availName a) a
 plusAvailEnv :: AvailEnv -> AvailEnv -> AvailEnv
 plusAvailEnv = plusNameEnv_C plusAvail
 
-lookupAvailEnv = lookupNameEnv
+lookupAvailEnv_maybe :: AvailEnv -> Name -> Maybe AvailInfo
+lookupAvailEnv_maybe = lookupNameEnv
+
+lookupAvailEnv :: AvailEnv -> Name -> AvailInfo
+lookupAvailEnv env n = case lookupNameEnv env n of
+                        Just avail -> avail
+                        Nothing    -> pprPanic "lookupAvailEnv" (ppr n)
 
 availEnvElts = nameEnvElts
 
@@ -667,13 +734,19 @@ data Inst
        TcThetaType     -- The (types of the) dictionaries to which the function
                        -- must be applied to get the method
 
-       TcTauType       -- The type of the method
+       TcTauType       -- The tau-type of the method
 
        InstLoc
 
-       -- INVARIANT: in (Method u f tys theta tau loc)
+       -- INVARIANT 1: in (Method u f tys theta tau loc)
        --      type of (f tys dicts(from theta)) = tau
 
+       -- INVARIANT 2: tau must not be of form (Pred -> Tau)
+       --   Reason: two methods are considerd equal if the 
+       --           base Id matches, and the instantiating types
+       --           match.  The TcThetaType should then match too.
+       --   This only bites in the call to tcInstClassOp in TcClassDcl.mkMethodBind
+
   | LitInst
        Id
        HsOverLit       -- The literal from the occurrence site