2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
4 \section[DsMonad]{@DsMonad@: monadery used in desugaring}
7 #include "HsVersions.h"
11 initDs, returnDs, thenDs, andDs, mapDs, listDs,
12 mapAndUnzipDs, zipWithDs,
14 newTyVarsDs, cloneTyVarsDs,
15 duplicateLocalDs, newSysLocalDs, newSysLocalsDs,
17 getSrcLocDs, putSrcLocDs,
19 extendEnvDs, lookupEnvDs, lookupEnvWithDefaultDs,
23 dsShadowWarn, dsIncompleteWarn,
25 DsMatchContext(..), DsMatchKind(..), pprDsWarnings,
26 DsWarnFlavour -- Nuke with 1.4
32 import Bag ( emptyBag, snocBag, bagToList )
33 import CmdLineOpts ( opt_SccGroup )
34 import CoreSyn ( SYN_IE(CoreExpr) )
35 import CoreUtils ( substCoreExpr )
36 import HsSyn ( OutPat )
37 import Id ( mkSysLocal, mkIdWithNewUniq,
38 lookupIdEnv, growIdEnvList, GenId, SYN_IE(IdEnv)
40 import PprType ( GenType, GenTyVar )
41 import PprStyle ( PprStyle(..) )
43 import SrcLoc ( noSrcLoc, SrcLoc )
44 import TcHsSyn ( SYN_IE(TypecheckedPat) )
45 import TyVar ( nullTyVarEnv, cloneTyVar, GenTyVar{-instance Eq-} )
46 import Unique ( Unique{-instances-} )
47 import UniqSupply ( splitUniqSupply, getUnique, getUniques,
48 mapUs, thenUs, returnUs, SYN_IE(UniqSM) )
49 import Util ( assoc, mapAccumL, zipWithEqual, panic )
54 Now the mondo monad magic (yes, @DsM@ is a silly name)---carry around
55 a @UniqueSupply@ and some annotations, which
56 presumably include source-file location information:
60 -> SrcLoc -- to put in pattern-matching error msgs
61 -> (FAST_STRING, FAST_STRING) -- "module"+"group" : for SCC profiling
64 -> (result, DsWarnings)
66 type DsWarnings = Bag (DsWarnFlavour, DsMatchContext)
67 -- The desugarer reports matches which are
68 -- completely shadowed or incomplete patterns
71 {-# INLINE returnDs #-}
73 -- initDs returns the UniqSupply out the end (not just the result)
77 -> FAST_STRING -- module name: for profiling; (group name: from switches)
81 initDs init_us env mod_name action
82 = action init_us noSrcLoc module_and_group env emptyBag
84 module_and_group = (mod_name, grp_name)
85 grp_name = case opt_SccGroup of
87 Nothing -> mod_name -- default: module name
89 thenDs :: DsM a -> (a -> DsM b) -> DsM b
90 andDs :: (a -> a -> a) -> DsM a -> DsM a -> DsM a
92 thenDs m1 m2 us loc mod_and_grp env warns
93 = case splitUniqSupply us of { (s1, s2) ->
94 case (m1 s1 loc mod_and_grp env warns) of { (result, warns1) ->
95 m2 result s2 loc mod_and_grp env warns1}}
97 andDs combiner m1 m2 us loc mod_and_grp env warns
98 = case splitUniqSupply us of { (s1, s2) ->
99 case (m1 s1 loc mod_and_grp env warns) of { (result1, warns1) ->
100 case (m2 s2 loc mod_and_grp env warns1) of { (result2, warns2) ->
101 (combiner result1 result2, warns2) }}}
103 returnDs :: a -> DsM a
104 returnDs result us loc mod_and_grp env warns = (result, warns)
106 listDs :: [DsM a] -> DsM [a]
107 listDs [] = returnDs []
110 listDs xs `thenDs` \ rs ->
113 mapDs :: (a -> DsM b) -> [a] -> DsM [b]
115 mapDs f [] = returnDs []
117 = f x `thenDs` \ r ->
118 mapDs f xs `thenDs` \ rs ->
121 mapAndUnzipDs :: (a -> DsM (b, c)) -> [a] -> DsM ([b], [c])
123 mapAndUnzipDs f [] = returnDs ([], [])
124 mapAndUnzipDs f (x:xs)
125 = f x `thenDs` \ (r1, r2) ->
126 mapAndUnzipDs f xs `thenDs` \ (rs1, rs2) ->
127 returnDs (r1:rs1, r2:rs2)
129 zipWithDs :: (a -> b -> DsM c) -> [a] -> [b] -> DsM [c]
131 zipWithDs f [] [] = returnDs []
132 zipWithDs f (x:xs) (y:ys)
133 = f x y `thenDs` \ r ->
134 zipWithDs f xs ys `thenDs` \ rs ->
136 -- Note: crashes if lists not equal length (like zipWithEqual)
139 And all this mysterious stuff is so we can occasionally reach out and
140 grab one or more names. @newLocalDs@ isn't exported---exported
141 functions are defined with it. The difference in name-strings makes
142 it easier to read debugging output.
144 newLocalDs :: FAST_STRING -> Type -> DsM Id
145 newLocalDs nm ty us loc mod_and_grp env warns
146 = case (getUnique us) of { assigned_uniq ->
147 (mkSysLocal nm assigned_uniq ty loc, warns) }
149 newSysLocalDs = newLocalDs SLIT("ds")
150 newSysLocalsDs tys = mapDs (newLocalDs SLIT("ds")) tys
151 newFailLocalDs = newLocalDs SLIT("fail")
153 duplicateLocalDs :: Id -> DsM Id
154 duplicateLocalDs old_local us loc mod_and_grp env warns
155 = case (getUnique us) of { assigned_uniq ->
156 (mkIdWithNewUniq old_local assigned_uniq, warns) }
158 cloneTyVarsDs :: [TyVar] -> DsM [TyVar]
159 cloneTyVarsDs tyvars us loc mod_and_grp env warns
160 = case (getUniques (length tyvars) us) of { uniqs ->
161 (zipWithEqual "cloneTyVarsDs" cloneTyVar tyvars uniqs, warns) }
165 newTyVarsDs :: [TyVar] -> DsM [TyVar]
167 newTyVarsDs tyvar_tmpls us loc mod_and_grp env warns
168 = case (getUniques (length tyvar_tmpls) us) of { uniqs ->
169 (zipWithEqual "newTyVarsDs" cloneTyVar tyvar_tmpls uniqs, warns) }
172 We can also reach out and either set/grab location information from
173 the @SrcLoc@ being carried around.
175 uniqSMtoDsM :: UniqSM a -> DsM a
177 uniqSMtoDsM u_action us loc mod_and_grp env warns
178 = (u_action us, warns)
180 getSrcLocDs :: DsM SrcLoc
181 getSrcLocDs us loc mod_and_grp env warns
184 putSrcLocDs :: SrcLoc -> DsM a -> DsM a
185 putSrcLocDs new_loc expr us old_loc mod_and_grp env warns
186 = expr us new_loc mod_and_grp env warns
188 dsShadowWarn :: DsMatchContext -> DsM ()
189 dsShadowWarn cxt us loc mod_and_grp env warns
190 = ((), warns `snocBag` (Shadowed, cxt))
192 dsIncompleteWarn :: DsMatchContext -> DsM ()
193 dsIncompleteWarn cxt us loc mod_and_grp env warns
194 = ((), warns `snocBag` (Incomplete, cxt))
198 getModuleAndGroupDs :: DsM (FAST_STRING, FAST_STRING)
199 getModuleAndGroupDs us loc mod_and_grp env warns
200 = (mod_and_grp, warns)
204 type DsIdEnv = IdEnv CoreExpr
206 extendEnvDs :: [(Id, CoreExpr)] -> DsM a -> DsM a
208 extendEnvDs pairs then_do us loc mod_and_grp old_env warns
209 = case splitUniqSupply us of { (s1, s2) ->
211 revised_pairs = subst_all pairs s1
213 then_do s2 loc mod_and_grp (growIdEnvList old_env revised_pairs) warns
216 subst_all pairs = mapUs subst pairs
219 = substCoreExpr old_env nullTyVarEnv expr `thenUs` \ new_expr ->
220 returnUs (v, new_expr)
222 lookupEnvDs :: Id -> DsM (Maybe CoreExpr)
223 lookupEnvDs id us loc mod_and_grp env warns
224 = (lookupIdEnv env id, warns)
225 -- Note: we don't assert anything about the Id
226 -- being looked up. There's not really anything
227 -- much to say about it. (WDP 94/06)
229 lookupEnvWithDefaultDs :: Id -> CoreExpr -> DsM CoreExpr
230 lookupEnvWithDefaultDs id deflt us loc mod_and_grp env warns
231 = (case (lookupIdEnv env id) of
236 lookupId :: [(Id, a)] -> Id -> a
238 = assoc "lookupId" env id
241 %************************************************************************
243 %* type synonym EquationInfo and access functions for its pieces *
245 %************************************************************************
248 data DsWarnFlavour = Shadowed | Incomplete deriving ()
251 = DsMatchContext DsMatchKind [TypecheckedPat] SrcLoc
263 pprDsWarnings :: PprStyle -> DsWarnings -> Pretty
264 pprDsWarnings sty warns
265 = ppAboves (map pp_warn (bagToList warns))
267 pp_warn (flavour, NoMatchContext) = ppSep [ppPStr SLIT("Warning: Some match is"),
269 Shadowed -> ppPStr SLIT("shadowed")
270 Incomplete -> ppPStr SLIT("possibly incomplete")]
272 pp_warn (flavour, DsMatchContext kind pats loc)
273 = ppHang (ppBesides [ppr PprForUser loc, ppPStr SLIT(": ")])
275 4 (pp_match kind pats))
277 msg = case flavour of
278 Shadowed -> ppPStr SLIT("Warning: Pattern match(es) completely overlapped")
279 Incomplete -> ppPStr SLIT("Warning: Possibly incomplete patterns")
281 pp_match (FunMatch fun) pats
282 = ppCat [ppPStr SLIT("in the definition of function"), ppQuote (ppr sty fun)]
284 pp_match CaseMatch pats
285 = ppHang (ppPStr SLIT("in a group of case alternatives beginning:"))
286 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot])
288 pp_match PatBindMatch pats
289 = ppHang (ppPStr SLIT("in a pattern binding:"))
290 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot])
292 pp_match LambdaMatch pats
293 = ppHang (ppPStr SLIT("in a lambda abstraction:"))
294 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot])
296 pp_match DoBindMatch pats
297 = ppHang (ppPStr SLIT("in a `do' pattern binding:"))
298 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot])
300 pp_arrow_dotdotdot = ppPStr SLIT("-> ...")