summaryrefslogtreecommitdiff
path: root/ghc/compiler/basicTypes/RdrName.lhs
blob: a4e34d40e796c1c28a9199d8d33b38e729390af8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%

\section[RdrName]{@RdrName@}

\begin{code}
module RdrName (
	RdrName(..),	-- Constructors exported only to BinIface

	-- Construction
	mkRdrUnqual, mkRdrQual, 
	mkUnqual, mkVarUnqual, mkQual, mkOrig,
	nameRdrName, getRdrName, 
	mkDerivedRdrName, 

	-- Destruction
	rdrNameModule, rdrNameOcc, setRdrNameSpace,
	isRdrDataCon, isRdrTyVar, isRdrTc, isQual, isUnqual, 
	isOrig, isOrig_maybe, isExact, isExact_maybe, isSrcRdrName,

	-- Printing;	instance Outputable RdrName

	-- LocalRdrEnv
	LocalRdrEnv, emptyLocalRdrEnv, extendLocalRdrEnv,
	lookupLocalRdrEnv, elemLocalRdrEnv,

	-- GlobalRdrEnv
	GlobalRdrEnv, emptyGlobalRdrEnv, mkGlobalRdrEnv, plusGlobalRdrEnv, 
	lookupGlobalRdrEnv, pprGlobalRdrEnv, globalRdrEnvElts,
	lookupGRE_RdrName, lookupGRE_Name,

	-- GlobalRdrElt, Provenance, ImportSpec
	GlobalRdrElt(..), Provenance(..), ImportSpec(..),
	isLocalGRE, unQualOK,
	pprNameProvenance
  ) where 

#include "HsVersions.h"

import OccName	( NameSpace, varName,
		  OccName, UserFS, 
		  setOccNameSpace,
		  mkOccFS, occNameFlavour,
		  isDataOcc, isTvOcc, isTcOcc,
		  OccEnv, emptyOccEnv, extendOccEnvList, lookupOccEnv, 
		  elemOccEnv, plusOccEnv_C, extendOccEnv_C, foldOccEnv,
		  occEnvElts
		)
import Module   ( ModuleName, mkModuleNameFS	)
import Name	( Name, NamedThing(getName), nameModuleName, nameParent_maybe,
		  nameOccName, isExternalName, nameSrcLoc )
import SrcLoc	( isGoodSrcLoc, SrcSpan )
import Outputable
import Util	( thenCmp )
\end{code}


%************************************************************************
%*									*
\subsection{The main data type}
%*									*
%************************************************************************

\begin{code}
data RdrName 
  = Unqual OccName
	-- Used for ordinary, unqualified occurrences 

  | Qual ModuleName OccName
	-- A qualified name written by the user in 
	-- *source* code.  The module isn't necessarily 
	-- the module where the thing is defined; 
	-- just the one from which it is imported

  | Orig ModuleName OccName
	-- An original name; the module is the *defining* module.
	-- This is used when GHC generates code that will be fed
	-- into the renamer (e.g. from deriving clauses), but where
	-- we want to say "Use Prelude.map dammit".  
 
  | Exact Name
	-- We know exactly the Name. This is used 
	--  (a) when the parser parses built-in syntax like "[]" 
	--	and "(,)", but wants a RdrName from it
	--  (b) when converting names to the RdrNames in IfaceTypes
	--	Here an Exact RdrName always contains an External Name
	--	(Internal Names are converted to simple Unquals)
	--  (c) by Template Haskell, when TH has generated a unique name
\end{code}


%************************************************************************
%*									*
\subsection{Simple functions}
%*									*
%************************************************************************

\begin{code}
rdrNameModule :: RdrName -> ModuleName
rdrNameModule (Qual m _) = m
rdrNameModule (Orig m _) = m
rdrNameModule (Exact n)  = nameModuleName n
rdrNameModule (Unqual n) = pprPanic "rdrNameModule" (ppr n)

rdrNameOcc :: RdrName -> OccName
rdrNameOcc (Qual _ occ) = occ
rdrNameOcc (Unqual occ) = occ
rdrNameOcc (Orig _ occ) = occ
rdrNameOcc (Exact name) = nameOccName name

setRdrNameSpace :: RdrName -> NameSpace -> RdrName
-- This rather gruesome function is used mainly by the parser
-- When parsing		data T a = T | T1 Int
-- we parse the data constructors as *types* because of parser ambiguities,
-- so then we need to change the *type constr* to a *data constr*
--
-- The original-name case *can* occur when parsing
-- 		data [] a = [] | a : [a]
-- For the orig-name case we return an unqualified name.
setRdrNameSpace (Unqual occ) ns = Unqual (setOccNameSpace ns occ)
setRdrNameSpace (Qual m occ) ns = Qual m (setOccNameSpace ns occ)
setRdrNameSpace (Orig m occ) ns = Orig m (setOccNameSpace ns occ)
setRdrNameSpace (Exact n)    ns = Orig (nameModuleName n)
				       (setOccNameSpace ns (nameOccName n))
\end{code}

\begin{code}
	-- These two are the basic constructors
mkRdrUnqual :: OccName -> RdrName
mkRdrUnqual occ = Unqual occ

mkRdrQual :: ModuleName -> OccName -> RdrName
mkRdrQual mod occ = Qual mod occ

mkOrig :: ModuleName -> OccName -> RdrName
mkOrig mod occ = Orig mod occ

---------------
mkDerivedRdrName :: Name -> (OccName -> OccName) -> (RdrName)
mkDerivedRdrName parent mk_occ
  = mkOrig (nameModuleName parent) (mk_occ (nameOccName parent))

---------------
	-- These two are used when parsing source files
	-- They do encode the module and occurrence names
mkUnqual :: NameSpace -> UserFS -> RdrName
mkUnqual sp n = Unqual (mkOccFS sp n)

mkVarUnqual :: UserFS -> RdrName
mkVarUnqual n = Unqual (mkOccFS varName n)

mkQual :: NameSpace -> (UserFS, UserFS) -> RdrName
mkQual sp (m, n) = Qual (mkModuleNameFS m) (mkOccFS sp n)

getRdrName :: NamedThing thing => thing -> RdrName
getRdrName name = nameRdrName (getName name)

nameRdrName :: Name -> RdrName
nameRdrName name = Exact name
-- Keep the Name even for Internal names, so that the
-- unique is still there for debug printing, particularly
-- of Types (which are converted to IfaceTypes before printing)

nukeExact :: Name -> RdrName
nukeExact n 
  | isExternalName n = Orig (nameModuleName n) (nameOccName n)
  | otherwise	     = Unqual (nameOccName n)
\end{code}

\begin{code}
isRdrDataCon rn = isDataOcc (rdrNameOcc rn)
isRdrTyVar   rn = isTvOcc   (rdrNameOcc rn)
isRdrTc      rn = isTcOcc   (rdrNameOcc rn)

isSrcRdrName (Unqual _) = True
isSrcRdrName (Qual _ _) = True
isSrcRdrName _		= False

isUnqual (Unqual _) = True
isUnqual other	    = False

isQual (Qual _ _) = True
isQual _	  = False

isOrig (Orig _ _) = True
isOrig _	  = False

isOrig_maybe (Orig m n) = Just (m,n)
isOrig_maybe _		= Nothing

isExact (Exact _) = True
isExact other	= False

isExact_maybe (Exact n) = Just n
isExact_maybe other	= Nothing
\end{code}


%************************************************************************
%*									*
\subsection{Instances}
%*									*
%************************************************************************

\begin{code}
instance Outputable RdrName where
    ppr (Exact name)   = ppr name
    ppr (Unqual occ)   = ppr occ <+> ppr_name_space occ
    ppr (Qual mod occ) = ppr mod <> dot <> ppr occ <+> ppr_name_space occ
    ppr (Orig mod occ) = ppr mod <> dot <> ppr occ <+> ppr_name_space occ

ppr_name_space occ = ifPprDebug (parens (occNameFlavour occ))

instance OutputableBndr RdrName where
    pprBndr _ n 
	| isTvOcc (rdrNameOcc n) = char '@' <+> ppr n
	| otherwise		 = ppr n

instance Eq RdrName where
    (Exact n1) 	  == (Exact n2)    = n1==n2
	-- Convert exact to orig
    (Exact n1) 	  == r2@(Orig _ _) = nukeExact n1 == r2
    r1@(Orig _ _) == (Exact n2)    = r1 == nukeExact n2

    (Orig m1 o1)  == (Orig m2 o2)  = m1==m2 && o1==o2
    (Qual m1 o1)  == (Qual m2 o2)  = m1==m2 && o1==o2
    (Unqual o1)   == (Unqual o2)   = o1==o2
    r1 == r2 = False

instance Ord RdrName where
    a <= b = case (a `compare` b) of { LT -> True;  EQ -> True;  GT -> False }
    a <	 b = case (a `compare` b) of { LT -> True;  EQ -> False; GT -> False }
    a >= b = case (a `compare` b) of { LT -> False; EQ -> True;  GT -> True  }
    a >	 b = case (a `compare` b) of { LT -> False; EQ -> False; GT -> True  }

	-- Exact < Unqual < Qual < Orig
	-- [Note: Apr 2004] We used to use nukeExact to convert Exact to Orig 
	-- 	before comparing so that Prelude.map == the exact Prelude.map, but 
	--	that meant that we reported duplicates when renaming bindings 
	--	generated by Template Haskell; e.g 
	--	do { n1 <- newName "foo"; n2 <- newName "foo"; 
	--	     <decl involving n1,n2> }
	--	I think we can do without this conversion
    compare (Exact n1) (Exact n2) = n1 `compare` n2
    compare (Exact n1) n2	  = LT

    compare (Unqual _)   (Exact _)    = GT
    compare (Unqual o1)  (Unqual  o2) = o1 `compare` o2
    compare (Unqual _)   _ 	      = LT

    compare (Qual _ _)   (Exact _)    = GT
    compare (Qual _ _)   (Unqual _)   = GT
    compare (Qual m1 o1) (Qual m2 o2) = (o1 `compare` o2) `thenCmp` (m1 `compare` m2) 
    compare (Qual _ _)   (Orig _ _)   = LT

    compare (Orig m1 o1) (Orig m2 o2) = (o1 `compare` o2) `thenCmp` (m1 `compare` m2) 
    compare (Orig _ _)   _	      = GT
\end{code}



%************************************************************************
%*									*
			LocalRdrEnv
%*									*
%************************************************************************

A LocalRdrEnv is used for local bindings (let, where, lambda, case)
It is keyed by OccName, because we never use it for qualified names.

\begin{code}
type LocalRdrEnv = OccEnv Name

emptyLocalRdrEnv = emptyOccEnv

extendLocalRdrEnv :: LocalRdrEnv -> [Name] -> LocalRdrEnv
extendLocalRdrEnv env names
  = extendOccEnvList env [(nameOccName n, n) | n <- names]

lookupLocalRdrEnv :: LocalRdrEnv -> RdrName -> Maybe Name
lookupLocalRdrEnv env (Exact name) = Just name
lookupLocalRdrEnv env (Unqual occ) = lookupOccEnv env occ
lookupLocalRdrEnv env other	   = Nothing

elemLocalRdrEnv :: RdrName -> LocalRdrEnv -> Bool
elemLocalRdrEnv rdr_name env 
  | isUnqual rdr_name = rdrNameOcc rdr_name `elemOccEnv` env
  | otherwise	      = False
\end{code}


%************************************************************************
%*									*
			GlobalRdrEnv
%*									*
%************************************************************************

\begin{code}
type GlobalRdrEnv = OccEnv [GlobalRdrElt]
	-- Keyed by OccName; when looking up a qualified name
	-- we look up the OccName part, and then check the Provenance
	-- to see if the appropriate qualification is valid.  This
	-- saves routinely doubling the size of the env by adding both
	-- qualified and unqualified names to the domain.
	--
	-- The list in the range is reqd because there may be name clashes
	-- These only get reported on lookup, not on construction

	-- INVARIANT: All the members of the list have distinct 
	--	      gre_name fields; that is, no duplicate Names

emptyGlobalRdrEnv = emptyOccEnv

globalRdrEnvElts :: GlobalRdrEnv -> [GlobalRdrElt]
globalRdrEnvElts env = foldOccEnv (++) [] env

data GlobalRdrElt 
  = GRE { gre_name   :: Name,
	  gre_prov   :: Provenance	-- Why it's in scope
    }

instance Outputable GlobalRdrElt where
  ppr gre = ppr name <+> pp_parent (nameParent_maybe name)
		<+> parens (pprNameProvenance gre)
	  where
	    name = gre_name gre
	    pp_parent (Just p) = brackets (text "parent:" <+> ppr p)
	    pp_parent Nothing  = empty

pprGlobalRdrEnv :: GlobalRdrEnv -> SDoc
pprGlobalRdrEnv env
  = vcat (map pp (occEnvElts env))
  where
    pp gres = ppr (nameOccName (gre_name (head gres))) <> colon <+> 
	      vcat [ ppr (gre_name gre) <+> pprNameProvenance gre
		   | gre <- gres]
\end{code}

\begin{code}
lookupGlobalRdrEnv :: GlobalRdrEnv -> OccName -> [GlobalRdrElt]
lookupGlobalRdrEnv env rdr_name = case lookupOccEnv env rdr_name of
					Nothing   -> []
					Just gres -> gres

lookupGRE_RdrName :: RdrName -> GlobalRdrEnv -> [GlobalRdrElt]
lookupGRE_RdrName rdr_name env
  = case lookupOccEnv env occ of
	Nothing -> []
	Just gres | isUnqual rdr_name -> filter unQualOK gres
		  | otherwise	      -> filter (hasQual mod) gres
  where
    mod = rdrNameModule rdr_name
    occ = rdrNameOcc rdr_name

lookupGRE_Name :: GlobalRdrEnv -> Name -> [GlobalRdrElt]
lookupGRE_Name env name
  = [ gre | gre <- lookupGlobalRdrEnv env (nameOccName name),
	    gre_name gre == name ]


isLocalGRE :: GlobalRdrElt -> Bool
isLocalGRE (GRE {gre_prov = LocalDef _}) = True
isLocalGRE other    		         = False

unQualOK :: GlobalRdrElt -> Bool
-- An unqualifed version of this thing is in scope
unQualOK (GRE {gre_prov = LocalDef _})    = True
unQualOK (GRE {gre_prov = Imported is _}) = not (all is_qual is)

hasQual :: ModuleName -> GlobalRdrElt -> Bool
-- A qualified version of this thing is in scope
hasQual mod (GRE {gre_prov = LocalDef m})    = m == mod
hasQual mod (GRE {gre_prov = Imported is _}) = any ((== mod) . is_as) is

plusGlobalRdrEnv :: GlobalRdrEnv -> GlobalRdrEnv -> GlobalRdrEnv
plusGlobalRdrEnv env1 env2 = plusOccEnv_C (foldr insertGRE) env1 env2

mkGlobalRdrEnv :: [GlobalRdrElt] -> GlobalRdrEnv
mkGlobalRdrEnv gres
  = foldr add emptyGlobalRdrEnv gres
  where
    add gre env = extendOccEnv_C (foldr insertGRE) env 
				 (nameOccName (gre_name gre)) 
				 [gre]

insertGRE :: GlobalRdrElt -> [GlobalRdrElt] -> [GlobalRdrElt]
insertGRE new_g [] = [new_g]
insertGRE new_g (old_g : old_gs)
	| gre_name new_g == gre_name old_g
	= new_g `plusGRE` old_g : old_gs
	| otherwise
	= old_g : insertGRE new_g old_gs

plusGRE :: GlobalRdrElt -> GlobalRdrElt -> GlobalRdrElt
-- Used when the gre_name fields match
plusGRE g1 g2
  = GRE { gre_name = gre_name g1,
	  gre_prov = gre_prov g1 `plusProv` gre_prov g2 }
\end{code}


%************************************************************************
%*									*
			Provenance
%*									*
%************************************************************************

The "provenance" of something says how it came to be in scope.

\begin{code}
data Provenance
  = LocalDef		-- Defined locally
	ModuleName

  | Imported 		-- Imported
	[ImportSpec]	-- INVARIANT: non-empty
	Bool		-- True iff the thing was named *explicitly* 
			-- in *any* of the import specs rather than being 
			-- imported as part of a group; 
	-- e.g.
	--	import B
	--	import C( T(..) )
	-- Here, everything imported by B, and the constructors of T
	-- are not named explicitly; only T is named explicitly.
	-- This info is used when warning of unused names.

data ImportSpec		-- Describes a particular import declaration
			-- Shared among all the Provenaces for a particular
			-- import declaration
  = ImportSpec {
	is_mod  :: ModuleName,		-- 'import Muggle'
					-- Note the Muggle may well not be 
					-- the defining module for this thing!
	is_as   :: ModuleName,		-- 'as M' (or 'Muggle' if there is no 'as' clause)
	is_qual :: Bool,		-- True <=> qualified (only)
	is_loc  :: SrcSpan }		-- Location of import statment

-- Comparison of provenance is just used for grouping 
-- error messages (in RnEnv.warnUnusedBinds)
instance Eq Provenance where
  p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False

instance Eq ImportSpec where
  p1 == p2 = case p1 `compare` p2 of EQ -> True; _ -> False

instance Ord Provenance where
   compare (LocalDef _) (LocalDef _)   = EQ
   compare (LocalDef _) (Imported _ _) = LT
   compare (Imported _ _) (LocalDef _) = GT
   compare (Imported is1 _) (Imported is2 _) = compare (head is1) (head is2)

instance Ord ImportSpec where
   compare is1 is2 = (is_mod is1 `compare` is_mod is2) `thenCmp` 
		     (is_loc is1 `compare` is_loc is2)
\end{code}

\begin{code}
plusProv :: Provenance -> Provenance -> Provenance
-- Choose LocalDef over Imported
-- There is an obscure bug lurking here; in the presence
-- of recursive modules, something can be imported *and* locally
-- defined, and one might refer to it with a qualified name from
-- the import -- but I'm going to ignore that because it makes
-- the isLocalGRE predicate so much nicer this way
plusProv (LocalDef m1) (LocalDef m2) 
  = pprPanic "plusProv" (ppr m1 <+> ppr m2)
plusProv p1@(LocalDef _) p2 = p1
plusProv p1 p2@(LocalDef _) = p2
plusProv (Imported is1 ex1) (Imported is2 ex2) 
  = Imported (is1++is2) (ex1 || ex2)

pprNameProvenance :: GlobalRdrElt -> SDoc
pprNameProvenance (GRE {gre_name = name, gre_prov = LocalDef _})
  = ptext SLIT("defined at") <+> ppr (nameSrcLoc name)
pprNameProvenance (GRE {gre_name = name, gre_prov = Imported (why:whys) _})
  = sep [ppr why, nest 2 (ppr_defn (nameSrcLoc name))]

-- If we know the exact definition point (which we may do with GHCi)
-- then show that too.  But not if it's just "imported from X".
ppr_defn loc | isGoodSrcLoc loc = parens (ptext SLIT("defined at") <+> ppr loc)
	     | otherwise	= empty

instance Outputable ImportSpec where
   ppr imp_spec
     = ptext SLIT("imported from") <+> ppr (is_mod imp_spec) 
	<+> ptext SLIT("at") <+> ppr (is_loc imp_spec)
\end{code}