[project @ 2005-03-01 05:49:43 by simonpj]
[ghc-hetmet.git] / ghc / compiler / deSugar / DsMonad.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[DsMonad]{@DsMonad@: monadery used in desugaring}
5
6 \begin{code}
7 module DsMonad (
8         DsM, mappM,
9         initDs, returnDs, thenDs, listDs, fixDs, mapAndUnzipDs, foldlDs,
10
11         newTyVarsDs, 
12         duplicateLocalDs, newSysLocalDs, newSysLocalsDs, newUniqueId,
13         newFailLocalDs,
14         getSrcSpanDs, putSrcSpanDs,
15         getModuleDs,
16         newUnique, 
17         UniqSupply, newUniqueSupply,
18         getDOptsDs,
19         dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon, dsLookupDataCon,
20
21         DsMetaEnv, DsMetaVal(..), dsLookupMetaEnv, dsExtendMetaEnv,
22
23         -- Warnings
24         DsWarning, dsWarn, 
25
26         -- Data types
27         DsMatchContext(..),
28         EquationInfo(..), MatchResult(..), DsWrapper, idWrapper,
29         CanItFail(..), orFail
30     ) where
31
32 #include "HsVersions.h"
33
34 import TcRnMonad
35 import CoreSyn          ( CoreExpr )
36 import HsSyn            ( HsExpr, HsMatchContext, Pat )
37 import TcIface          ( tcIfaceGlobal )
38 import RdrName          ( GlobalRdrEnv )
39 import HscTypes         ( TyThing(..), TypeEnv, HscEnv, 
40                           tyThingId, tyThingTyCon, tyThingDataCon, unQualInScope )
41 import Bag              ( emptyBag, snocBag, Bag )
42 import DataCon          ( DataCon )
43 import TyCon            ( TyCon )
44 import DataCon          ( DataCon )
45 import Id               ( mkSysLocal, setIdUnique, Id )
46 import Module           ( Module )
47 import Var              ( TyVar, setTyVarUnique )
48 import Outputable
49 import SrcLoc           ( noSrcSpan, SrcSpan )
50 import Type             ( Type )
51 import UniqSupply       ( UniqSupply, uniqsFromSupply )
52 import Name             ( Name, nameOccName )
53 import NameEnv
54 import OccName          ( occNameFS )
55 import CmdLineOpts      ( DynFlags )
56 import ErrUtils         ( WarnMsg, mkWarnMsg )
57 import Bag              ( mapBag )
58
59 import DATA_IOREF       ( newIORef, readIORef )
60
61 infixr 9 `thenDs`
62 \end{code}
63
64 %************************************************************************
65 %*                                                                      *
66                 Data types for the desugarer
67 %*                                                                      *
68 %************************************************************************
69
70 \begin{code}
71 data DsMatchContext
72   = DsMatchContext (HsMatchContext Name) [Pat Id] SrcSpan
73   | NoMatchContext
74   deriving ()
75
76 data EquationInfo
77   = EqnInfo { eqn_wrap :: DsWrapper,    -- Bindings
78               eqn_pats :: [Pat Id],     -- The patterns for an eqn
79               eqn_rhs  :: MatchResult } -- What to do after match
80
81 type DsWrapper = CoreExpr -> CoreExpr
82 idWrapper e = e
83
84 -- The semantics of (match vs (EqnInfo wrap pats rhs)) is the MatchResult
85 --      \fail. wrap (case vs of { pats -> rhs fail })
86 -- where vs are not in the domain of wrap
87
88
89 -- A MatchResult is an expression with a hole in it
90 data MatchResult
91   = MatchResult
92         CanItFail       -- Tells whether the failure expression is used
93         (CoreExpr -> DsM CoreExpr)
94                         -- Takes a expression to plug in at the
95                         -- failure point(s). The expression should
96                         -- be duplicatable!
97
98 data CanItFail = CanFail | CantFail
99
100 orFail CantFail CantFail = CantFail
101 orFail _        _        = CanFail
102 \end{code}
103
104
105 %************************************************************************
106 %*                                                                      *
107                 Monad stuff
108 %*                                                                      *
109 %************************************************************************
110
111 Now the mondo monad magic (yes, @DsM@ is a silly name)---carry around
112 a @UniqueSupply@ and some annotations, which
113 presumably include source-file location information:
114 \begin{code}
115 type DsM result = TcRnIf DsGblEnv DsLclEnv result
116
117 -- Compatibility functions
118 fixDs    = fixM
119 thenDs   = thenM
120 returnDs = returnM
121 listDs   = sequenceM
122 foldlDs  = foldlM
123 mapAndUnzipDs = mapAndUnzipM
124
125
126 type DsWarning = (SrcSpan, SDoc)
127         -- Not quite the same as a WarnMsg, we have an SDoc here 
128         -- and we'll do the print_unqual stuff later on to turn it
129         -- into a Doc.
130
131 data DsGblEnv = DsGblEnv {
132         ds_mod     :: Module,                   -- For SCC profiling
133         ds_warns   :: IORef (Bag DsWarning),    -- Warning messages
134         ds_if_env  :: (IfGblEnv, IfLclEnv)      -- Used for looking up global, 
135                                                 -- possibly-imported things
136     }
137
138 data DsLclEnv = DsLclEnv {
139         ds_meta    :: DsMetaEnv,        -- Template Haskell bindings
140         ds_loc     :: SrcSpan           -- to put in pattern-matching error msgs
141      }
142
143 -- Inside [| |] brackets, the desugarer looks 
144 -- up variables in the DsMetaEnv
145 type DsMetaEnv = NameEnv DsMetaVal
146
147 data DsMetaVal
148    = Bound Id           -- Bound by a pattern inside the [| |]. 
149                         -- Will be dynamically alpha renamed.
150                         -- The Id has type THSyntax.Var
151
152    | Splice (HsExpr Id) -- These bindings are introduced by
153                         -- the PendingSplices on a HsBracketOut
154
155 -- initDs returns the UniqSupply out the end (not just the result)
156
157 initDs  :: HscEnv
158         -> Module -> GlobalRdrEnv -> TypeEnv
159         -> DsM a
160         -> IO (a, Bag WarnMsg)
161
162 initDs hsc_env mod rdr_env type_env thing_inside
163   = do  { warn_var <- newIORef emptyBag
164         ; let { if_genv = IfGblEnv { if_rec_types = Just (mod, return type_env) }
165               ; if_lenv = mkIfLclEnv mod (ptext SLIT("GHC error in desugarer lookup in") <+> ppr mod)
166               ; gbl_env = DsGblEnv { ds_mod = mod, 
167                                      ds_if_env = (if_genv, if_lenv),
168                                      ds_warns = warn_var }
169               ; lcl_env = DsLclEnv { ds_meta = emptyNameEnv, 
170                                      ds_loc = noSrcSpan } }
171
172         ; res <- initTcRnIf 'd' hsc_env gbl_env lcl_env thing_inside
173
174         ; warns <- readIORef warn_var
175         ; return (res, mapBag mk_warn warns)
176         }
177    where
178     print_unqual = unQualInScope rdr_env
179
180     mk_warn :: (SrcSpan,SDoc) -> WarnMsg
181     mk_warn (loc,sdoc) = mkWarnMsg loc print_unqual sdoc
182 \end{code}
183
184 %************************************************************************
185 %*                                                                      *
186                 Operations in the monad
187 %*                                                                      *
188 %************************************************************************
189
190 And all this mysterious stuff is so we can occasionally reach out and
191 grab one or more names.  @newLocalDs@ isn't exported---exported
192 functions are defined with it.  The difference in name-strings makes
193 it easier to read debugging output.
194
195 \begin{code}
196 -- Make a new Id with the same print name, but different type, and new unique
197 newUniqueId :: Name -> Type -> DsM Id
198 newUniqueId id ty
199   = newUnique   `thenDs` \ uniq ->
200     returnDs (mkSysLocal (occNameFS (nameOccName id)) uniq ty)
201
202 duplicateLocalDs :: Id -> DsM Id
203 duplicateLocalDs old_local 
204   = newUnique   `thenDs` \ uniq ->
205     returnDs (setIdUnique old_local uniq)
206
207 newSysLocalDs, newFailLocalDs :: Type -> DsM Id
208 newSysLocalDs ty
209   = newUnique   `thenDs` \ uniq ->
210     returnDs (mkSysLocal FSLIT("ds") uniq ty)
211
212 newSysLocalsDs tys = mappM newSysLocalDs tys
213
214 newFailLocalDs ty 
215   = newUnique   `thenDs` \ uniq ->
216     returnDs (mkSysLocal FSLIT("fail") uniq ty)
217         -- The UserLocal bit just helps make the code a little clearer
218 \end{code}
219
220 \begin{code}
221 newTyVarsDs :: [TyVar] -> DsM [TyVar]
222 newTyVarsDs tyvar_tmpls 
223   = newUniqueSupply     `thenDs` \ uniqs ->
224     returnDs (zipWith setTyVarUnique tyvar_tmpls (uniqsFromSupply uniqs))
225 \end{code}
226
227 We can also reach out and either set/grab location information from
228 the @SrcSpan@ being carried around.
229
230 \begin{code}
231 getDOptsDs :: DsM DynFlags
232 getDOptsDs = getDOpts
233
234 getModuleDs :: DsM Module
235 getModuleDs = do { env <- getGblEnv; return (ds_mod env) }
236
237 getSrcSpanDs :: DsM SrcSpan
238 getSrcSpanDs = do { env <- getLclEnv; return (ds_loc env) }
239
240 putSrcSpanDs :: SrcSpan -> DsM a -> DsM a
241 putSrcSpanDs new_loc thing_inside = updLclEnv (\ env -> env {ds_loc = new_loc}) thing_inside
242
243 dsWarn :: DsWarning -> DsM ()
244 dsWarn (loc,warn) = do { env <- getGblEnv; updMutVar (ds_warns env) (`snocBag` (loc,msg)) }
245             where
246               msg = ptext SLIT("Warning:") <+> warn
247 \end{code}
248
249 \begin{code}
250 dsLookupGlobal :: Name -> DsM TyThing
251 -- Very like TcEnv.tcLookupGlobal
252 dsLookupGlobal name 
253   = do  { env <- getGblEnv
254         ; setEnvs (ds_if_env env)
255                   (tcIfaceGlobal name) }
256
257 dsLookupGlobalId :: Name -> DsM Id
258 dsLookupGlobalId name 
259   = dsLookupGlobal name         `thenDs` \ thing ->
260     returnDs (tyThingId thing)
261
262 dsLookupTyCon :: Name -> DsM TyCon
263 dsLookupTyCon name
264   = dsLookupGlobal name         `thenDs` \ thing ->
265     returnDs (tyThingTyCon thing)
266
267 dsLookupDataCon :: Name -> DsM DataCon
268 dsLookupDataCon name
269   = dsLookupGlobal name         `thenDs` \ thing ->
270     returnDs (tyThingDataCon thing)
271 \end{code}
272
273 \begin{code}
274 dsLookupMetaEnv :: Name -> DsM (Maybe DsMetaVal)
275 dsLookupMetaEnv name = do { env <- getLclEnv; return (lookupNameEnv (ds_meta env) name) }
276
277 dsExtendMetaEnv :: DsMetaEnv -> DsM a -> DsM a
278 dsExtendMetaEnv menv thing_inside
279   = updLclEnv (\env -> env { ds_meta = ds_meta env `plusNameEnv` menv }) thing_inside
280 \end{code}
281
282