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