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,
22 dsShadowWarn, dsIncompleteWarn,
24 DsMatchContext(..), DsMatchKind(..), pprDsWarnings,
25 DsWarnFlavour -- Nuke with 1.4
31 import Bag ( emptyBag, snocBag, bagToList, Bag )
32 import BasicTypes ( SYN_IE(Module) )
33 import CmdLineOpts ( opt_PprUserLength )
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),
41 import PprType ( GenType, GenTyVar )
42 import Outputable ( pprQuote, Outputable(..), PprStyle(..) )
44 import SrcLoc ( noSrcLoc, SrcLoc )
45 import TcHsSyn ( SYN_IE(TypecheckedPat) )
46 import Type ( SYN_IE(Type) )
47 import TyVar ( nullTyVarEnv, cloneTyVar, GenTyVar{-instance Eq-}, SYN_IE(TyVar) )
48 import Unique ( Unique{-instances-} )
49 import UniqSupply ( splitUniqSupply, getUnique, getUniques,
50 mapUs, thenUs, returnUs, SYN_IE(UniqSM),
52 import Util ( assoc, mapAccumL, zipWithEqual, panic )
57 Now the mondo monad magic (yes, @DsM@ is a silly name)---carry around
58 a @UniqueSupply@ and some annotations, which
59 presumably include source-file location information:
63 -> SrcLoc -- to put in pattern-matching error msgs
64 -> (Module, Group) -- module + group name : for SCC profiling
67 -> (result, DsWarnings)
69 type DsWarnings = Bag (DsWarnFlavour, DsMatchContext)
70 -- The desugarer reports matches which are
71 -- completely shadowed or incomplete patterns
73 type Group = FAST_STRING
77 {-# INLINE returnDs #-}
79 -- initDs returns the UniqSupply out the end (not just the result)
83 -> (Module, Group) -- module name: for profiling; (group name: from switches)
87 initDs init_us env module_and_group action
88 = action init_us noSrcLoc module_and_group env emptyBag
90 thenDs :: DsM a -> (a -> DsM b) -> DsM b
91 andDs :: (a -> a -> a) -> DsM a -> DsM a -> DsM a
93 thenDs m1 m2 us loc mod_and_grp env warns
94 = case splitUniqSupply us of { (s1, s2) ->
95 case (m1 s1 loc mod_and_grp env warns) of { (result, warns1) ->
96 m2 result s2 loc mod_and_grp env warns1}}
98 andDs combiner m1 m2 us loc mod_and_grp env warns
99 = case splitUniqSupply us of { (s1, s2) ->
100 case (m1 s1 loc mod_and_grp env warns) of { (result1, warns1) ->
101 case (m2 s2 loc mod_and_grp env warns1) of { (result2, warns2) ->
102 (combiner result1 result2, warns2) }}}
104 returnDs :: a -> DsM a
105 returnDs result us loc mod_and_grp env warns = (result, warns)
107 listDs :: [DsM a] -> DsM [a]
108 listDs [] = returnDs []
111 listDs xs `thenDs` \ rs ->
114 mapDs :: (a -> DsM b) -> [a] -> DsM [b]
116 mapDs f [] = returnDs []
118 = f x `thenDs` \ r ->
119 mapDs f xs `thenDs` \ rs ->
122 mapAndUnzipDs :: (a -> DsM (b, c)) -> [a] -> DsM ([b], [c])
124 mapAndUnzipDs f [] = returnDs ([], [])
125 mapAndUnzipDs f (x:xs)
126 = f x `thenDs` \ (r1, r2) ->
127 mapAndUnzipDs f xs `thenDs` \ (rs1, rs2) ->
128 returnDs (r1:rs1, r2:rs2)
130 zipWithDs :: (a -> b -> DsM c) -> [a] -> [b] -> DsM [c]
132 zipWithDs f [] ys = returnDs []
133 zipWithDs f (x:xs) (y:ys)
134 = f x y `thenDs` \ r ->
135 zipWithDs f xs ys `thenDs` \ rs ->
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.
145 newLocalDs :: FAST_STRING -> Type -> DsM Id
146 newLocalDs nm ty us loc mod_and_grp env warns
147 = case (getUnique us) of { assigned_uniq ->
148 (mkSysLocal nm assigned_uniq ty loc, warns) }
150 newSysLocalDs = newLocalDs SLIT("ds")
151 newSysLocalsDs tys = mapDs (newLocalDs SLIT("ds")) tys
152 newFailLocalDs = newLocalDs SLIT("fail")
154 duplicateLocalDs :: Id -> DsM Id
155 duplicateLocalDs old_local us loc mod_and_grp env warns
156 = case (getUnique us) of { assigned_uniq ->
157 (mkIdWithNewUniq old_local assigned_uniq, warns) }
159 cloneTyVarsDs :: [TyVar] -> DsM [TyVar]
160 cloneTyVarsDs tyvars us loc mod_and_grp env warns
161 = case (getUniques (length tyvars) us) of { uniqs ->
162 (zipWithEqual "cloneTyVarsDs" cloneTyVar tyvars uniqs, warns) }
166 newTyVarsDs :: [TyVar] -> DsM [TyVar]
168 newTyVarsDs tyvar_tmpls us loc mod_and_grp env warns
169 = case (getUniques (length tyvar_tmpls) us) of { uniqs ->
170 (zipWithEqual "newTyVarsDs" cloneTyVar tyvar_tmpls uniqs, warns) }
173 We can also reach out and either set/grab location information from
174 the @SrcLoc@ being carried around.
176 uniqSMtoDsM :: UniqSM a -> DsM a
178 uniqSMtoDsM u_action us loc mod_and_grp env warns
179 = (u_action us, warns)
181 getSrcLocDs :: DsM SrcLoc
182 getSrcLocDs us loc mod_and_grp env warns
185 putSrcLocDs :: SrcLoc -> DsM a -> DsM a
186 putSrcLocDs new_loc expr us old_loc mod_and_grp env warns
187 = expr us new_loc mod_and_grp env warns
189 dsShadowWarn :: DsMatchContext -> DsM ()
190 dsShadowWarn cxt us loc mod_and_grp env warns
191 = ((), warns `snocBag` (Shadowed, cxt))
193 dsIncompleteWarn :: DsMatchContext -> DsM ()
194 dsIncompleteWarn cxt us loc mod_and_grp env warns
195 = ((), warns `snocBag` (Incomplete, cxt))
199 getModuleAndGroupDs :: DsM (FAST_STRING, FAST_STRING)
200 getModuleAndGroupDs us loc mod_and_grp env warns
201 = (mod_and_grp, warns)
205 type DsIdEnv = IdEnv Id
207 extendEnvDs :: [(Id, Id)] -> DsM a -> DsM a
209 extendEnvDs pairs then_do us loc mod_and_grp old_env warns
210 = then_do us loc mod_and_grp (growIdEnvList old_env pairs) warns
212 lookupEnvDs :: Id -> DsM Id
213 lookupEnvDs id us loc mod_and_grp env warns
214 = (case (lookupIdEnv env id) of
220 %************************************************************************
222 %* type synonym EquationInfo and access functions for its pieces *
224 %************************************************************************
227 data DsWarnFlavour = Shadowed | Incomplete deriving ()
230 = DsMatchContext DsMatchKind [TypecheckedPat] SrcLoc
242 pprDsWarnings :: PprStyle -> DsWarnings -> Doc
243 pprDsWarnings sty warns
244 = vcat (map pp_warn (bagToList warns))
246 pp_warn (flavour, NoMatchContext) = sep [ptext SLIT("Warning: Some match is"),
248 Shadowed -> ptext SLIT("shadowed")
249 Incomplete -> ptext SLIT("possibly incomplete")]
251 pp_warn (flavour, DsMatchContext kind pats loc)
252 = hang (hcat [ppr (PprForUser opt_PprUserLength) loc, ptext SLIT(": ")])
254 4 (pp_match kind pats))
256 msg = case flavour of
257 Shadowed -> ptext SLIT("Warning: Pattern match(es) completely overlapped")
258 Incomplete -> ptext SLIT("Warning: Possibly incomplete patterns")
260 pp_match (FunMatch fun) pats
261 = hsep [ptext SLIT("in the definition of function"), ppr sty fun]
263 pp_match CaseMatch pats
264 = hang (ptext SLIT("in a group of case alternatives beginning:"))
267 pp_match PatBindMatch pats
268 = hang (ptext SLIT("in a pattern binding:"))
271 pp_match LambdaMatch pats
272 = hang (ptext SLIT("in a lambda abstraction:"))
275 pp_match DoBindMatch pats
276 = hang (ptext SLIT("in a `do' pattern binding:"))
279 ppr_pats pats = pprQuote sty $ \ sty ->
280 sep [sep (map (ppr sty) pats), ptext SLIT("-> ...")]