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
|
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
%
\section[E]{Main typechecker environment}
\begin{code}
#include "HsVersions.h"
module E (
E,
mkE, nullE,
getE_GlobalVals, getE_TCE, getE_CE,
plusE_TCE, plusE_CE,
growE_LVE, plusE_GVE, tvOfE,
lookupE_Value, lookupE_ValueQuietly,
lookupE_ClassOpByKey, lookupE_Binder,
GVE(..), LVE(..),
plusLVE, nullLVE,
plusGVE, nullGVE, unitGVE, -- UNUSED: rngGVE,
-- and to make the interface self-sufficient...
CE(..), Id, Name, TCE(..), TyVar, Maybe, UniqFM
) where
import CE
import TCE
import UniqFM -- basic env handling code
import AbsPrel ( PrimOp
IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
)
import AbsUniType ( getClassOps, extractTyVarsFromTy,
getClassBigSig, getClassOpString, TyVar,
TyVarTemplate, ClassOp, Class, Arity(..),
TauType(..)
IF_ATTACK_PRAGMAS(COMMA cmpTyVar COMMA cmpClass)
)
import Id ( getIdUniType, Id, IdInfo )
import Maybes ( MaybeErr(..), Maybe(..) )
import Name -- Name(..), etc.
import Outputable -- def of ppr, etc.
import Pretty -- to pretty-print error messages
import UniqSet -- this use of Sets is a HACK (WDP 94/05)
import Unique -- *Key stuff
import Util
\end{code}
%************************************************************************
%* *
\subsection{Type declarations}
%* *
%************************************************************************
\begin{code}
data E
= MkE TCE -- type environment
GVB -- "global" value bindings; no free type vars
LVB -- "local" value bindings; may have free type vars
CE -- class environment
mkE :: TCE -> CE -> E
mkE tce ce = MkE tce nullGVB nullLVB ce
nullE :: E
nullE = MkE nullTCE nullGVB nullLVB nullCE
\end{code}
The ``local'' and ``global'' bindings, @LVB@ and @GVB@, are
non-exported synonyms. The important thing is that @GVB@ doesn't
contain any free type variables. This is used (only) in @tvOfE@,
which extracts free type variables from the environment. It's quite a
help to have this separation because there may be quite a large bunch
of imported things in the @GVB@, all of which are guaranteed
polymorphic.
\begin{code}
type LVB = UniqFM Id -- Locals just have a Unique
type GVB = UniqFM Id -- Globals might be a prelude thing; hence IdKey
nullLVB = (emptyUFM :: LVB)
nullGVB = (emptyUFM :: GVB)
\end{code}
The ``local'' and ``global'' value environments are not part of @E@ at
all, but is used to provide increments to the value bindings. GVE are
carries the implication that there are no free type variables.
\begin{code}
type LVE = [(Name, Id)] -- Maps Names to Ids
type GVE = [(Name, Id)] -- Maps Names to Ids
nullLVE = ([] :: LVE)
plusLVE a b = a ++ b
nullGVE = ([] :: GVE)
unitGVE n i = ( [(n, i)] :: GVE )
-- UNUSED: rngGVE gve = map snd gve
plusGVE a b = a ++ b
\end{code}
%************************************************************************
%* *
\subsection{Value environment stuff}
%* *
%************************************************************************
Looking up things should mostly succeed, because the renamer should
have spotted all out-of-scope names. The exception is instances.
The ``Quietly'' version is for pragmas, where lookups very well may
fail. @lookup_val@ is the internal function that does the work.
\begin{code}
lookupE_Value :: E -> Name -> Id
lookupE_ValueQuietly :: E -> Name -> Maybe Id
lookupE_Value e nm
= case lookup_val e nm of
Succeeded id -> id
Failed (should_panic, msg)
-> if should_panic then panic msg else error msg
lookupE_ValueQuietly e nm
= case lookup_val e nm of
Succeeded id -> Just id
Failed _ -> Nothing
\end{code}
\begin{code}
lookup_val (MkE _ gvb lvb ce) name
= case name of
WiredInVal id -> Succeeded id
PreludeVal key _ -> case (lookupDirectlyUFM gvb key) of
Just id -> Succeeded id
Nothing -> Failed (False, prelude_err_msg)
ClassOpName uniq clas_name _ tag -> id_from_env uniq
-- You might think that top-level ids are guaranteed to have no
-- free tyvars, so look only in gvb; but you'd be wrong! When
-- type-checking the RHS of recursive top-level defns, the name
-- of the thing is bound to a *monomorphic* type, which is later
-- generalised. So we have to look in the LVE too.
OtherTopId uniq _ -> id_from_env uniq
-- Short names could be in either GVB or LVB
Short uniq _ -> id_from_env uniq
funny_name -> pprPanic "lookup_val: funny Name" (ppr PprDebug funny_name)
where
prelude_err_msg = "ERROR: in looking up a built-in Prelude value!\n(This can happen if you use `-fno-implicit-prelude'\nor you hide the system's Prelude.hi in some way.)"
id_from_env uniq
= case (lookupDirectlyUFM lvb uniq) of
Just id -> Succeeded id
Nothing ->
case (lookupDirectlyUFM gvb uniq) of
Just id -> Succeeded id
Nothing -> Failed (True, -- should panic
("lookupE_Value: unbound name: "++(ppShow 80 (ppr PprShowAll name))))
\end{code}
For Prelude things that we reach out and grab, we have only an @Unique@.
\begin{code}
lookupE_ClassOpByKey :: E -> Unique{-ClassKey-} -> FAST_STRING -> Id
lookupE_ClassOpByKey (MkE _ gvb lvb ce) clas_key op_str
= let
clas = lookupCE ce (PreludeClass clas_key bottom)
bottom = pprPanic ("lookupE_ClassOpByKey: "++(_UNPK_ op_str))
(ppAbove (pprUnique clas_key) (ppr PprShowAll (rngCE ce)))
(clas_tyvar_tmpl, scs, sc_sel_ids, ops, op_sel_ids, defm_ids)
= getClassBigSig clas
in
case [ op_sel_id | (op, op_sel_id) <- ops `zip` op_sel_ids,
op_str == getClassOpString op ] of
[op] -> op
-- Seems a rather horrible way to do it (ToDo)
\end{code}
@lookupE_Binder@ is like @lookupE_Value@, but it is used for {\em
binding} occurrences of a variable, rather than {\em uses}. The
difference is that there should always be an entry in the LVE for
binding occurrences. Just a sanity check now, really.
\begin{code}
lookupE_Binder :: E -> Name -> Id
lookupE_Binder (MkE _ _ lvb _) name
= case (lookupDirectlyUFM lvb (name2uniq name)) of
Just id -> id
Nothing -> pprPanic "lookupE_Binder: unbound name: " (ppr PprShowAll name)
\end{code}
\begin{code}
getE_GlobalVals :: E -> [Id]
getE_GlobalVals (MkE tce gvb lvb ce)
= let
result = eltsUFM gvb ++ eltsUFM lvb
in
-- pprTrace "Global Ids:" (ppr PprShowAll result)
result
plusE_GVE :: E -> GVE -> E
plusE_GVE (MkE tce gvb lvb ce) gve
= let
new_stuff = listToUFM_Directly [(name2idkey n, i) | (n,i) <- gve ]
in
MkE tce (plusUFM gvb new_stuff) lvb ce
where
name2idkey (PreludeVal k _) = k
name2idkey (OtherTopId u _) = u
name2idkey (ClassOpName u _ _ _) = u
growE_LVE :: E -> LVE -> E
growE_LVE (MkE tce gvb lvb ce) lve
= let
new_stuff = listToUFM_Directly [(name2uniq n, i) | (n,i) <- lve ]
in
MkE tce gvb (plusUFM lvb new_stuff) ce
-- ToDo: move this elsewhere??
name2uniq (Short u _) = u
name2uniq (OtherTopId u _) = u
name2uniq (ClassOpName u _ _ _) = panic "growE_LVE:name2uniq"
\end{code}
Return the free type variables of an LVE; there are no duplicates in
the result---hence all the @Set@ bozo-ery. The free tyvars can only
occur in the LVB part.
\begin{code}
tvOfE :: E -> [TyVar]
tvOfE (MkE tce gvb lvb ce)
= uniqSetToList (mkUniqSet (
foldr ((++) . extractTyVarsFromTy . getIdUniType) [] (eltsUFM lvb)
))
\end{code}
%************************************************************************
%* *
%*
\subsection{Type and class environments}
%* *
%************************************************************************
\begin{code}
getE_TCE :: E -> TCE
getE_TCE (MkE tce gvb lvb ce) = tce
getE_CE :: E -> CE
getE_CE (MkE tce gvb lvb ce) = ce
plusE_TCE :: E -> TCE -> E
plusE_TCE (MkE tce gvb lvb ce) tce'
= MkE (plusTCE tce' tce) gvb lvb ce
plusE_CE :: E -> CE -> E
plusE_CE (MkE tce gvb lvb ce) ce'
= MkE tce gvb lvb (plusCE ce ce')
\end{code}
|