2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[RnUtils]{Functions used by both renaming passes}
7 #include "HsVersions.h"
10 SYN_IE(RnEnv), SYN_IE(QualNames),
11 SYN_IE(UnqualNames), SYN_IE(ScopeStack),
12 emptyRnEnv, extendGlobalRnEnv, extendLocalRnEnv,
13 lookupRnEnv, lookupGlobalRnEnv, lookupTcRnEnv,
23 IMPORT_1_3(List(partition))
25 import Bag ( Bag, emptyBag, snocBag, unionBags )
26 import CmdLineOpts ( opt_CompilingGhcInternals )
27 import ErrUtils ( addShortErrLocLine )
28 import FiniteMap ( FiniteMap, emptyFM, isEmptyFM,
29 lookupFM, addListToFM, addToFM, eltsFM )
30 import Maybes ( maybeToBool )
31 import Name ( RdrName(..), ExportFlag(..),
32 isQual, pprNonSym, getLocalName, isLocallyDefined )
33 import PprStyle ( PprStyle(..) )
35 import RnHsSyn ( RnName )
36 import Util ( assertPanic )
39 *********************************************************
41 \subsection{RnEnv: renaming environment}
43 *********************************************************
45 Separate FiniteMaps are kept for lookup up Qual names,
46 Unqual names and Local names.
49 type RnEnv = ((QualNames, UnqualNames, QualNames, UnqualNames), ScopeStack)
51 type QualNames = FiniteMap (FAST_STRING,Module) RnName
52 type UnqualNames = FiniteMap FAST_STRING RnName
53 type ScopeStack = FiniteMap FAST_STRING RnName
56 extendGlobalRnEnv :: RnEnv -> [(RdrName,RnName)] -> [(RdrName,RnName)]
57 -> (RnEnv, Bag (RdrName, RnName, RnName))
58 extendLocalRnEnv :: Bool -> RnEnv -> [RnName] -> (RnEnv, [RnName])
59 lookupRnEnv :: RnEnv -> RdrName -> Maybe RnName
60 lookupGlobalRnEnv :: RnEnv -> RdrName -> Maybe RnName
61 lookupTcRnEnv :: RnEnv -> RdrName -> Maybe RnName
63 getLocalsFromRnEnv :: RnEnv -> ([RnName], [RnName])
64 -- grabs the locally defined names from the unqual envs
67 If the @RdrName@ is a @Qual@, @lookupValue@ looks it up in the global
68 value QualNames. If it is @Unqual@, it looks it up first in the
69 ScopeStack, and if it isn't found there, then in the global
72 @lookupTcRnEnv@ looks up tycons/classes in the alternative global
75 @extendGlobalRnEnv@ adds global names to the RnEnv. It takes separate
76 value and tycon/class name lists. It returns any duplicate names
79 @extendRnEnv@ adds new local names to the ScopeStack in an RnEnv.
80 It optionally reports any shadowed names.
84 = ((emptyFM, emptyFM, emptyFM, emptyFM), emptyFM)
86 extendGlobalRnEnv ((qual, unqual, tc_qual, tc_unqual), stack) val_list tc_list
87 = ASSERT(isEmptyFM stack)
88 (((qual', unqual', tc_qual', tc_unqual'), stack), tc_dups `unionBags` dups)
90 (qual', unqual', dups) = extend_global qual unqual val_list
91 (tc_qual', tc_unqual', tc_dups) = extend_global tc_qual tc_unqual tc_list
93 extend_global qual unqual rdr_list = (qual', unqual', dups)
95 (qual_list, unqual_list) = partition (isQual.fst) rdr_list
96 qual_in = map mk_qual qual_list
97 unqual_in = map mk_unqual unqual_list
98 mk_qual (Qual m s, rn) = ((s,m), rn)
99 mk_unqual (Unqual s, rn) = (s, rn)
101 (qual', qual_dups) = do_dups qual_in qual emptyBag (\ (s,m) -> Qual m s)
102 (unqual', unqual_dups) = do_dups unqual_in unqual emptyBag Unqual
104 dups = unqual_dups `unionBags` qual_dups
106 do_dups [] fm dups to_rdr = (fm, dups)
107 do_dups ((k,v):rest) fm dups to_rdr
108 = case lookupFM fm k of
109 Nothing -> do_dups rest (addToFM fm k v) dups to_rdr
110 Just cur -> do_dups rest fm (dups `snocBag` (to_rdr k, cur, v)) to_rdr
113 extendLocalRnEnv report_shadows (global, stack) new_local
114 = ((global, new_stack), dups)
116 (new_stack, dups) = extend new_local stack
119 = if report_shadows then
120 do_shadows names stack []
122 (addListToFM stack [ (getLocalName n, n) | n <- names], [])
124 do_shadows [] stack dups = (stack, dups)
125 do_shadows (name:names) stack dups
126 = do_shadows names (addToFM stack str name) ext_dups
128 str = getLocalName name
129 ext_dups = if maybeToBool (lookupFM stack str)
134 lookupRnEnv ((qual, unqual, _, _), stack) rdr
136 Unqual str -> lookup stack str (lookup unqual str Nothing)
137 Qual mod str -> lookup qual (str,mod)
138 (if not opt_CompilingGhcInternals -- see below
139 then -- pprTrace "lookupRnEnv:" (ppAboves (ppCat [ppPStr mod, ppPStr str] : [ ppCat [ppPStr m, ppPStr s] | (s,m) <- keysFM qual ])) $
141 else lookup unqual str Nothing)
143 lookup fm thing do_on_fail
144 = case lookupFM fm thing of
145 found@(Just name) -> found
146 Nothing -> do_on_fail
148 lookupGlobalRnEnv ((qual, unqual, _, _), _) rdr
150 Unqual str -> lookupFM unqual str
151 Qual mod str -> case (lookupFM qual (str,mod)) of
153 Nothing -> if not opt_CompilingGhcInternals then
155 else -- "[]" may have turned into "Prelude.[]" and
156 -- we are actually compiling "data [] a = ...";
157 -- maybe the right thing is to get "Prelude.[]"
158 -- into the "qual" table...
161 lookupTcRnEnv ((_, _, tc_qual, tc_unqual), _) rdr
163 Unqual str -> lookupFM tc_unqual str
164 Qual mod str -> case (lookupFM tc_qual (str,mod)) of -- as above
166 Nothing -> if not opt_CompilingGhcInternals then
169 lookupFM tc_unqual str
171 getLocalsFromRnEnv ((_, vals, _, tcs), _)
172 = (filter isLocallyDefined (eltsFM vals),
173 filter isLocallyDefined (eltsFM tcs))
176 *********************************************************
178 \subsection{Export Flag Functions}
180 *********************************************************
183 lubExportFlag ExportAll ExportAll = ExportAll
184 lubExportFlag ExportAll ExportAbs = ExportAll
185 lubExportFlag ExportAbs ExportAll = ExportAll
186 lubExportFlag ExportAbs ExportAbs = ExportAbs
189 *********************************************************
191 \subsection{Errors used *more than once* in the renamer}
193 *********************************************************
196 qualNameErr descriptor (name,locn)
197 = addShortErrLocLine locn ( \ sty ->
198 ppBesides [ppStr "invalid use of qualified ", ppStr descriptor, ppStr ": ", pprNonSym sty name ] )
200 dupNamesErr descriptor ((name1,locn1) : dup_things) sty
201 = ppAboves (item1 : map dup_item dup_things)
204 = addShortErrLocLine locn1 (\ sty ->
205 ppBesides [ppStr "multiple declarations of a ", ppStr descriptor, ppStr " `",
206 pprNonSym sty name1, ppStr "'" ]) sty
208 dup_item (name, locn)
209 = addShortErrLocLine locn (\ sty ->
210 ppBesides [ppStr "here was another declaration of `",
211 pprNonSym sty name, ppStr "'" ]) sty