1825928e20b6a0480cc264dde5abe42756584472
[ghc-hetmet.git] / ghc / compiler / rename / RnUtils.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[RnUtils]{Functions used by both renaming passes}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module RnUtils (
10         RnEnv(..), QualNames(..),
11         UnqualNames(..), ScopeStack(..),
12         emptyRnEnv, extendGlobalRnEnv, extendLocalRnEnv,
13         lookupRnEnv, lookupGlobalRnEnv, lookupTcRnEnv,
14
15         lubExportFlag,
16
17         unknownNameErr,
18         badClassOpErr,
19         qualNameErr,
20         dupNamesErr,
21         shadowedNameWarn,
22         multipleOccWarn
23     ) where
24
25 import Ubiq
26
27 import Bag              ( Bag, emptyBag, snocBag, unionBags )
28 import ErrUtils         ( addShortErrLocLine, addShortWarnLocLine, addErrLoc )
29 import FiniteMap        ( FiniteMap, emptyFM, isEmptyFM,
30                           lookupFM, addListToFM, addToFM )
31 import Maybes           ( maybeToBool )
32 import Name             ( RdrName(..), isQual, pprNonSym, getLocalName, ExportFlag(..) )
33 import PprStyle         ( PprStyle(..) )
34 import Pretty
35 import RnHsSyn          ( RnName )
36 import Util             ( assertPanic )
37 \end{code}
38
39 *********************************************************
40 *                                                       *
41 \subsection{RnEnv: renaming environment}
42 *                                                       *
43 *********************************************************
44
45 Seperate FiniteMaps are kept for lookup up Qual names,
46 Unqual names and Local names.
47
48 \begin{code}
49 type RnEnv = ((QualNames, UnqualNames, QualNames, UnqualNames), ScopeStack)
50
51 type QualNames    = FiniteMap (FAST_STRING,Module) RnName
52 type UnqualNames  = FiniteMap FAST_STRING RnName
53 type ScopeStack   = FiniteMap FAST_STRING RnName
54
55 emptyRnEnv        :: RnEnv
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
62 \end{code}
63
64 If the @RdrName@ is a @Qual@, @lookupValue@ looks it up in the global
65 value QualNames.  If it is @Unqual@, it looks it up first in the
66 ScopeStack, and if it isn't found there, then in the global
67 vaule Unqual Names.
68
69 @lookupTcRnEnv@ looks up tycons/classes in the alternative global
70 name space.
71
72 @extendGlobalRnEnv@ adds global names to the RnEnv. It takes separate
73 value and tycon/class name lists. It returns any duplicate names
74 seperately.
75
76 @extendRnEnv@ adds new local names to the ScopeStack in an RnEnv.
77 It optionally reports any shadowed names.
78
79 \begin{code}
80 emptyRnEnv
81   = ((emptyFM, emptyFM, emptyFM, emptyFM), emptyFM)
82
83 extendGlobalRnEnv ((qual, unqual, tc_qual, tc_unqual), stack) val_list tc_list
84   = ASSERT(isEmptyFM stack)
85     (((qual', unqual', tc_qual', tc_unqual'), stack), tc_dups `unionBags` dups)
86   where
87     (qual', unqual', dups)          = extend_global qual unqual val_list
88     (tc_qual', tc_unqual', tc_dups) = extend_global tc_qual tc_unqual tc_list
89
90     extend_global qual unqual rdr_list = (qual', unqual', dups)
91       where
92         (qual_list, unqual_list) = partition (isQual.fst) rdr_list
93         qual_in   = map mk_qual qual_list
94         unqual_in = map mk_unqual unqual_list
95         mk_qual   (Qual m s, rn) = ((s,m), rn)
96         mk_unqual (Unqual s, rn) = (s, rn)
97
98         (qual', qual_dups)     = do_dups qual_in qual emptyBag (\ (s,m) -> Qual m s)
99         (unqual', unqual_dups) = do_dups unqual_in unqual emptyBag Unqual
100
101         dups = unqual_dups `unionBags` qual_dups
102
103         do_dups [] fm dups to_rdr = (fm, dups)
104         do_dups ((k,v):rest) fm dups to_rdr
105           = case lookupFM fm k of
106               Nothing  -> do_dups rest (addToFM fm k v) dups to_rdr
107               Just cur -> do_dups rest fm (dups `snocBag` (to_rdr k, cur, v)) to_rdr
108
109
110 extendLocalRnEnv report_shadows (global, stack) new_local
111   = ((global, new_stack), dups)
112   where
113     (new_stack, dups) = extend new_local stack
114
115     extend names stack
116       = if report_shadows then
117             do_shadows names stack []
118         else
119             (addListToFM stack [ (getLocalName n, n) | n <- names], []) 
120
121     do_shadows [] stack dups = (stack, dups)
122     do_shadows (name:names) stack dups
123       = do_shadows names (addToFM stack str name) ext_dups
124       where
125         str = getLocalName name
126         ext_dups = if maybeToBool (lookupFM stack str)
127                    then name:dups
128                    else dups
129
130
131 lookupRnEnv ((qual, unqual, _, _), stack) rdr
132   = case rdr of 
133       Unqual str   -> lookup stack str (lookup unqual str Nothing)
134       Qual mod str -> lookup qual (str,mod) Nothing
135   where
136     lookup fm thing do_on_fail
137       = case lookupFM fm thing of
138             found@(Just name) -> found
139             Nothing           -> do_on_fail
140
141 lookupGlobalRnEnv ((qual, unqual, _, _), _) rdr
142   = case rdr of 
143       Unqual str   -> lookupFM unqual str
144       Qual mod str -> lookupFM qual (str,mod)
145
146 lookupTcRnEnv ((_, _, tc_qual, tc_unqual), _) rdr
147   = case rdr of 
148       Unqual str   -> lookupFM tc_unqual str
149       Qual mod str -> lookupFM tc_qual (str,mod)
150 \end{code}
151
152 *********************************************************
153 *                                                       *
154 \subsection{Export Flag Functions}
155 *                                                       *
156 *********************************************************
157
158 \begin{code}
159 lubExportFlag ExportAll ExportAll = ExportAll
160 lubExportFlag ExportAll ExportAbs = ExportAll
161 lubExportFlag ExportAbs ExportAll = ExportAll
162 lubExportFlag ExportAbs ExportAbs = ExportAbs
163 \end{code}
164
165 *********************************************************
166 *                                                       *
167 \subsection{Errors used in RnMonad}
168 *                                                       *
169 *********************************************************
170
171 \begin{code}
172 unknownNameErr descriptor name locn
173   = addShortErrLocLine locn ( \ sty ->
174     ppBesides [ppStr "undefined ", ppStr descriptor, ppStr ": ", pprNonSym sty name] )
175
176 badClassOpErr clas op locn
177   = addErrLoc locn "" ( \ sty ->
178     ppBesides [ppChar '`', pprNonSym sty op, ppStr "' is not an operation of class `",
179               ppr sty clas, ppStr "'"] )
180
181 qualNameErr descriptor (name,locn)
182   = addShortErrLocLine locn ( \ sty ->
183     ppBesides [ppStr "invalid use of qualified ", ppStr descriptor, ppStr ": ", pprNonSym sty name ] )
184
185 dupNamesErr descriptor ((name1,locn1) : dup_things) sty
186   = ppAboves (item1 : map dup_item dup_things)
187   where
188     item1
189       = addShortErrLocLine locn1 (\ sty ->
190         ppBesides [ppStr "multiple declarations of a ", ppStr descriptor, ppStr " `", 
191                    pprNonSym sty name1, ppStr "'" ]) sty
192
193     dup_item (name, locn)
194       = addShortErrLocLine locn (\ sty ->
195         ppBesides [ppStr "here was another declaration of `",
196                    pprNonSym sty name, ppStr "'" ]) sty
197
198 shadowedNameWarn locn shadow
199   = addShortWarnLocLine locn ( \ sty ->
200     ppBesides [ppStr "more than one value with the same name (shadowing): ", ppr sty shadow] )
201
202 multipleOccWarn (name, occs) sty
203   = ppBesides [ppStr "warning:multiple names used to refer to `", ppr sty name, ppStr "': ",
204                ppInterleave ppComma (map (ppr sty) occs)]
205 \end{code}
206