+type ExportAvails = (FiniteMap ModuleName Avails,
+ -- Used to figure out "module M" export specifiers
+ -- Includes avails only from *unqualified* imports
+ -- (see 1.4 Report Section 5.1.1)
+
+ AvailEnv) -- Used to figure out all other export specifiers.
+\end{code}
+
+%===================================================
+\subsubsection{ INTERFACE FILE STUFF}
+%===================================================
+
+\begin{code}
+type ExportItem = (ModuleName, [RdrAvailInfo])
+type IfaceDeprecs = Maybe (Either DeprecTxt [(RdrName,DeprecTxt)])
+ -- Nothing => NoDeprecs
+ -- Just (Left t) => DeprecAll
+ -- Just (Right p) => DeprecSome
+
+data ParsedIface
+ = ParsedIface {
+ pi_mod :: Module, -- Complete with package info
+ pi_vers :: Version, -- Module version number
+ pi_orphan :: WhetherHasOrphans, -- Whether this module has orphans
+ pi_usages :: [ImportVersion OccName], -- Usages
+ pi_exports :: (Version, [ExportItem]), -- Exports
+ pi_decls :: [(Version, RdrNameTyClDecl)], -- Local definitions
+ pi_fixity :: [RdrNameFixitySig], -- Local fixity declarations,
+ pi_insts :: [RdrNameInstDecl], -- Local instance declarations
+ pi_rules :: (Version, [RdrNameRuleDecl]), -- Rules, with their version
+ pi_deprecs :: IfaceDeprecs -- Deprecations
+ }
+\end{code}
+
+%************************************************************************
+%* *
+\subsection{The renamer state}
+%* *
+%************************************************************************
+
+\begin{code}
+data Ifaces = Ifaces {
+ -- PERSISTENT FIELDS
+ iPIT :: PackageIfaceTable,
+ -- The ModuleIFaces for modules in other packages
+ -- whose interfaces we have opened
+ -- The declarations in these interface files are held in
+ -- iDecls, iInsts, iRules (below), not in the mi_decls fields
+ -- of the iPIT. What _is_ in the iPIT is:
+ -- * The Module
+ -- * Version info
+ -- * Its exports
+ -- * Fixities
+ -- * Deprecations
+ -- The iPIT field is initialised from the compiler's persistent
+ -- package symbol table, and the renamer incrementally adds
+ -- to it.
+
+ iDecls :: DeclsMap,
+ -- A single, global map of Names to unslurped decls
+
+ iInsts :: IfaceInsts,
+ -- The as-yet un-slurped instance decls; this bag is depleted when we
+ -- slurp an instance decl so that we don't slurp the same one twice.
+ -- Each is 'gated' by the names that must be available before
+ -- this instance decl is needed.
+
+ iRules :: IfaceRules,
+ -- Similar to instance decls, only for rules
+
+ -- EPHEMERAL FIELDS
+ -- These fields persist during the compilation of a single module only
+ iImpModInfo :: ImportedModuleInfo,
+ -- Modules that we know something about, because they are mentioned
+ -- in interface files, BUT which we have not loaded yet.
+ -- No module is both in here and in the PIT
+
+ iSlurp :: NameSet,
+ -- All the names (whether "big" or "small", whether wired-in or not,
+ -- whether locally defined or not) that have been slurped in so far.
+
+ iVSlurp :: (ModuleSet, NameSet)
+ -- The Names are all the (a) non-wired-in
+ -- (b) "big"
+ -- (c) non-locally-defined
+ -- (d) home-package
+ -- names that have been slurped in so far, with their versions.
+ -- This is used to generate the "usage" information for this module.
+ -- Subset of the previous field.
+ -- The module set is the non-home-package modules from which we have
+ -- slurped at least one name.
+ -- It's worth keeping separately, because there's no very easy
+ -- way to distinguish the "big" names from the "non-big" ones.
+ -- But this is a decision we might want to revisit.
+ }
+
+type ImportedModuleInfo = FiniteMap ModuleName (WhetherHasOrphans, IsBootInterface)
+ -- Contains info ONLY about modules that have not yet
+ --- been loaded into the iPIT
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Main monad code}
+%* *
+%************************************************************************
+
+\begin{code}
+runRn dflags hit hst pcs mod do_rn
+ = do { (pcs, msgs, r) <- initRn dflags hit hst pcs mod do_rn ;
+ printErrorsAndWarnings alwaysQualify msgs ;
+ return (pcs, errorsFound msgs, r)
+ }
+
+initRn :: DynFlags
+ -> HomeIfaceTable -> HomeSymbolTable
+ -> PersistentCompilerState
+ -> Module
+ -> RnMG t
+ -> IO (PersistentCompilerState, Messages, t)
+
+initRn dflags hit hst pcs mod do_rn
+ = do
+ let prs = pcs_PRS pcs
+ let pte = pcs_PTE pcs
+ let ifaces = Ifaces { iPIT = pcs_PIT pcs,
+ iDecls = prsDecls prs,
+ iInsts = prsInsts prs,
+ iRules = prsRules prs,
+
+ iImpModInfo = emptyFM,
+ iSlurp = unitNameSet (mkUnboundName dummyRdrVarName),
+ -- Pretend that the dummy unbound name has already been
+ -- slurped. This is what's returned for an out-of-scope name,
+ -- and we don't want thereby to try to suck it in!
+ iVSlurp = (emptyModuleSet, emptyNameSet)
+ }
+ names_var <- newIORef (prsOrig prs)
+ errs_var <- newIORef (emptyBag,emptyBag)
+ iface_var <- newIORef ifaces
+ let rn_down = RnDown { rn_mod = mod,
+ rn_loc = noSrcLoc,
+
+ rn_dflags = dflags,
+ rn_hit = hit,
+ rn_done = lookupType hst pte,
+
+ rn_ns = names_var,
+ rn_errs = errs_var,
+ rn_ifaces = iface_var,
+ }
+
+ -- do the business
+ res <- do_rn rn_down ()
+
+ -- Grab state and record it
+ (warns, errs) <- readIORef errs_var
+ new_ifaces <- readIORef iface_var
+ new_orig <- readIORef names_var
+ let new_prs = prs { prsOrig = new_orig,
+ prsDecls = iDecls new_ifaces,
+ prsInsts = iInsts new_ifaces,
+ prsRules = iRules new_ifaces }
+ let new_pcs = pcs { pcs_PIT = iPIT new_ifaces,
+ pcs_PRS = new_prs }
+
+ return (new_pcs, (warns, errs), res)
+
+initRnMS :: GlobalRdrEnv -> LocalFixityEnv -> RnMode
+ -> RnMS a -> RnM d a
+
+initRnMS rn_env fixity_env mode thing_inside rn_down g_down
+ -- The fixity_env appears in both the rn_fixenv field
+ -- and in the HIT. See comments with RnHiFiles.lookupFixityRn
+ = let
+ s_down = SDown { rn_genv = rn_env, rn_lenv = emptyRdrEnv,
+ rn_fixenv = fixity_env, rn_mode = mode }
+ in
+ thing_inside rn_down s_down
+
+initIfaceRnMS :: Module -> RnMS r -> RnM d r
+initIfaceRnMS mod thing_inside
+ = initRnMS emptyRdrEnv emptyLocalFixityEnv InterfaceMode $
+ setModuleRn mod thing_inside
+\end{code}
+
+@renameDerivedCode@ is used to rename stuff ``out-of-line'';
+that is, not as part of the main renamer.
+Sole examples: derived definitions,
+which are only generated in the type checker.
+
+The @NameSupply@ includes a @UniqueSupply@, so if you call it more than
+once you must either split it, or install a fresh unique supply.
+
+\begin{code}
+renameDerivedCode :: DynFlags
+ -> Module
+ -> PersistentRenamerState
+ -> RnMS r
+ -> r
+
+renameDerivedCode dflags mod prs thing_inside
+ = unsafePerformIO $
+ -- It's not really unsafe! When renaming source code we
+ -- only do any I/O if we need to read in a fixity declaration;
+ -- and that doesn't happen in pragmas etc
+
+ do { us <- mkSplitUniqSupply 'r'
+ ; names_var <- newIORef ((prsOrig prs) { origNS = us })
+ ; errs_var <- newIORef (emptyBag,emptyBag)
+
+ ; let rn_down = RnDown { rn_dflags = dflags,
+ rn_loc = generatedSrcLoc, rn_ns = names_var,
+ rn_errs = errs_var,
+ rn_mod = mod,
+ rn_done = bogus "rn_done",
+ rn_hit = bogus "rn_hit",
+ rn_ifaces = bogus "rn_ifaces"
+ }
+ ; let s_down = SDown { rn_mode = InterfaceMode,
+ -- So that we can refer to PrelBase.True etc
+ rn_genv = emptyRdrEnv, rn_lenv = emptyRdrEnv,
+ rn_fixenv = emptyLocalFixityEnv }
+
+ ; result <- thing_inside rn_down s_down
+ ; messages <- readIORef errs_var
+
+ ; if bad messages then
+ do { hPutStr stderr "Urk! renameDerivedCode found errors or warnings"
+ ; printErrorsAndWarnings alwaysQualify messages
+ }
+ else
+ return()
+
+ ; return result
+ }
+ where
+#ifdef DEBUG
+ bad messages = errorsFound messages || warningsFound messages