2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
6 @DsMonad@: monadery used in desugaring
10 DsM, mapM, mapAndUnzipM,
11 initDs, initDsTc, fixDs,
12 foldlM, foldrM, ifOptM,
13 Applicative(..),(<$>),
15 newTyVarsDs, newLocalName,
16 duplicateLocalDs, newSysLocalDs, newSysLocalsDs, newUniqueId,
18 getSrcSpanDs, putSrcSpanDs,
21 UniqSupply, newUniqueSupply,
22 getDOptsDs, getGhcModeDs, doptDs,
23 dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon, dsLookupDataCon,
26 DsMetaEnv, DsMetaVal(..), dsLookupMetaEnv, dsExtendMetaEnv,
29 DsWarning, warnDs, failWithDs,
33 EquationInfo(..), MatchResult(..), DsWrapper, idDsWrapper,
65 %************************************************************************
67 Data types for the desugarer
69 %************************************************************************
73 = DsMatchContext (HsMatchContext Name) SrcSpan
78 = EqnInfo { eqn_pats :: [Pat Id], -- The patterns for an eqn
79 eqn_rhs :: MatchResult } -- What to do after match
81 type DsWrapper = CoreExpr -> CoreExpr
82 idDsWrapper :: DsWrapper
85 -- The semantics of (match vs (EqnInfo wrap pats rhs)) is the MatchResult
86 -- \fail. wrap (case vs of { pats -> rhs fail })
87 -- where vs are not bound by wrap
90 -- A MatchResult is an expression with a hole in it
93 CanItFail -- Tells whether the failure expression is used
94 (CoreExpr -> DsM CoreExpr)
95 -- Takes a expression to plug in at the
96 -- failure point(s). The expression should
99 data CanItFail = CanFail | CantFail
101 orFail :: CanItFail -> CanItFail -> CanItFail
102 orFail CantFail CantFail = CantFail
107 %************************************************************************
111 %************************************************************************
113 Now the mondo monad magic (yes, @DsM@ is a silly name)---carry around
114 a @UniqueSupply@ and some annotations, which
115 presumably include source-file location information:
117 type DsM result = TcRnIf DsGblEnv DsLclEnv result
119 -- Compatibility functions
120 fixDs :: (a -> DsM a) -> DsM a
123 type DsWarning = (SrcSpan, SDoc)
124 -- Not quite the same as a WarnMsg, we have an SDoc here
125 -- and we'll do the print_unqual stuff later on to turn it
128 data DsGblEnv = DsGblEnv {
129 ds_mod :: Module, -- For SCC profiling
130 ds_unqual :: PrintUnqualified,
131 ds_msgs :: IORef Messages, -- Warning messages
132 ds_if_env :: (IfGblEnv, IfLclEnv) -- Used for looking up global,
133 -- possibly-imported things
136 data DsLclEnv = DsLclEnv {
137 ds_meta :: DsMetaEnv, -- Template Haskell bindings
138 ds_loc :: SrcSpan -- to put in pattern-matching error msgs
141 -- Inside [| |] brackets, the desugarer looks
142 -- up variables in the DsMetaEnv
143 type DsMetaEnv = NameEnv DsMetaVal
146 = Bound Id -- Bound by a pattern inside the [| |].
147 -- Will be dynamically alpha renamed.
148 -- The Id has type THSyntax.Var
150 | Splice (HsExpr Id) -- These bindings are introduced by
151 -- the PendingSplices on a HsBracketOut
154 -> Module -> GlobalRdrEnv -> TypeEnv
157 -- Print errors and warnings, if any arise
159 initDs hsc_env mod rdr_env type_env thing_inside
160 = do { msg_var <- newIORef (emptyBag, emptyBag)
161 ; let dflags = hsc_dflags hsc_env
162 ; (ds_gbl_env, ds_lcl_env) <- mkDsEnvs dflags mod rdr_env type_env msg_var
164 ; either_res <- initTcRnIf 'd' hsc_env ds_gbl_env ds_lcl_env $
165 tryM thing_inside -- Catch exceptions (= errors during desugaring)
167 -- Display any errors and warnings
168 -- Note: if -Werror is used, we don't signal an error here.
169 ; msgs <- readIORef msg_var
170 ; printErrorsAndWarnings dflags msgs
172 ; let final_res | errorsFound dflags msgs = Nothing
173 | otherwise = case either_res of
174 Right res -> Just res
175 Left exn -> pprPanic "initDs" (text (show exn))
176 -- The (Left exn) case happens when the thing_inside throws
177 -- a UserError exception. Then it should have put an error
178 -- message in msg_var, so we just discard the exception
182 initDsTc :: DsM a -> TcM a
183 initDsTc thing_inside
184 = do { this_mod <- getModule
185 ; tcg_env <- getGblEnv
186 ; msg_var <- getErrsVar
188 ; let type_env = tcg_type_env tcg_env
189 rdr_env = tcg_rdr_env tcg_env
190 ; ds_envs <- liftIO $ mkDsEnvs dflags this_mod rdr_env type_env msg_var
191 ; setEnvs ds_envs thing_inside }
193 mkDsEnvs :: DynFlags -> Module -> GlobalRdrEnv -> TypeEnv -> IORef Messages -> IO (DsGblEnv, DsLclEnv)
194 mkDsEnvs dflags mod rdr_env type_env msg_var
195 = do -- TODO: unnecessarily monadic
196 let if_genv = IfGblEnv { if_rec_types = Just (mod, return type_env) }
197 if_lenv = mkIfLclEnv mod (ptext (sLit "GHC error in desugarer lookup in") <+> ppr mod)
198 gbl_env = DsGblEnv { ds_mod = mod,
199 ds_if_env = (if_genv, if_lenv),
200 ds_unqual = mkPrintUnqualified dflags rdr_env,
202 lcl_env = DsLclEnv { ds_meta = emptyNameEnv,
205 return (gbl_env, lcl_env)
209 %************************************************************************
211 Operations in the monad
213 %************************************************************************
215 And all this mysterious stuff is so we can occasionally reach out and
216 grab one or more names. @newLocalDs@ isn't exported---exported
217 functions are defined with it. The difference in name-strings makes
218 it easier to read debugging output.
221 -- Make a new Id with the same print name, but different type, and new unique
222 newUniqueId :: Name -> Type -> DsM Id
223 newUniqueId id ty = do
225 return (mkSysLocal (occNameFS (nameOccName id)) uniq ty)
227 duplicateLocalDs :: Id -> DsM Id
228 duplicateLocalDs old_local = do
230 return (setIdUnique old_local uniq)
232 newSysLocalDs, newFailLocalDs :: Type -> DsM Id
233 newSysLocalDs ty = do
235 return (mkSysLocal (fsLit "ds") uniq ty)
237 newSysLocalsDs :: [Type] -> DsM [Id]
238 newSysLocalsDs tys = mapM newSysLocalDs tys
240 newFailLocalDs ty = do
242 return (mkSysLocal (fsLit "fail") uniq ty)
243 -- The UserLocal bit just helps make the code a little clearer
247 newTyVarsDs :: [TyVar] -> DsM [TyVar]
248 newTyVarsDs tyvar_tmpls = do
249 uniqs <- newUniqueSupply
250 return (zipWith setTyVarUnique tyvar_tmpls (uniqsFromSupply uniqs))
253 We can also reach out and either set/grab location information from
254 the @SrcSpan@ being carried around.
257 getDOptsDs :: DsM DynFlags
258 getDOptsDs = getDOpts
260 doptDs :: DynFlag -> TcRnIf gbl lcl Bool
263 getGhcModeDs :: DsM GhcMode
264 getGhcModeDs = getDOptsDs >>= return . ghcMode
266 getModuleDs :: DsM Module
267 getModuleDs = do { env <- getGblEnv; return (ds_mod env) }
269 getSrcSpanDs :: DsM SrcSpan
270 getSrcSpanDs = do { env <- getLclEnv; return (ds_loc env) }
272 putSrcSpanDs :: SrcSpan -> DsM a -> DsM a
273 putSrcSpanDs new_loc thing_inside = updLclEnv (\ env -> env {ds_loc = new_loc}) thing_inside
275 warnDs :: SDoc -> DsM ()
276 warnDs warn = do { env <- getGblEnv
277 ; loc <- getSrcSpanDs
278 ; let msg = mkWarnMsg loc (ds_unqual env)
279 (ptext (sLit "Warning:") <+> warn)
280 ; updMutVar (ds_msgs env) (\ (w,e) -> (w `snocBag` msg, e)) }
283 failWithDs :: SDoc -> DsM a
285 = do { env <- getGblEnv
286 ; loc <- getSrcSpanDs
287 ; let msg = mkErrMsg loc (ds_unqual env) err
288 ; updMutVar (ds_msgs env) (\ (w,e) -> (w, e `snocBag` msg))
294 dsLookupGlobal :: Name -> DsM TyThing
295 -- Very like TcEnv.tcLookupGlobal
297 = do { env <- getGblEnv
298 ; setEnvs (ds_if_env env)
299 (tcIfaceGlobal name) }
301 dsLookupGlobalId :: Name -> DsM Id
302 dsLookupGlobalId name
303 = tyThingId <$> dsLookupGlobal name
305 dsLookupTyCon :: Name -> DsM TyCon
307 = tyThingTyCon <$> dsLookupGlobal name
309 dsLookupDataCon :: Name -> DsM DataCon
311 = tyThingDataCon <$> dsLookupGlobal name
313 dsLookupClass :: Name -> DsM Class
315 = tyThingClass <$> dsLookupGlobal name
319 dsLookupMetaEnv :: Name -> DsM (Maybe DsMetaVal)
320 dsLookupMetaEnv name = do { env <- getLclEnv; return (lookupNameEnv (ds_meta env) name) }
322 dsExtendMetaEnv :: DsMetaEnv -> DsM a -> DsM a
323 dsExtendMetaEnv menv thing_inside
324 = updLclEnv (\env -> env { ds_meta = ds_meta env `plusNameEnv` menv }) thing_inside