2 #include "HsVersions.h"
5 SYN_IE(TcM), SYN_IE(NF_TcM), TcDown, TcEnv,
9 returnTc, thenTc, thenTc_, mapTc, listTc,
10 foldrTc, foldlTc, mapAndUnzipTc, mapAndUnzip3Tc,
11 mapBagTc, fixTc, tryTc,
13 returnNF_Tc, thenNF_Tc, thenNF_Tc_, mapNF_Tc, fixNF_Tc, forkNF_Tc,
15 listNF_Tc, mapAndUnzipNF_Tc, mapBagNF_Tc,
17 checkTc, checkTcM, checkMaybeTc, checkMaybeTcM,
18 failTc, warnTc, recoverTc, recoverNF_Tc,
21 tcGetDefaultTys, tcSetDefaultTys,
22 tcGetUnique, tcGetUniques,
24 tcAddSrcLoc, tcGetSrcLoc,
25 tcAddErrCtxtM, tcSetErrCtxtM,
26 tcAddErrCtxt, tcSetErrCtxt,
28 tcNewMutVar, tcReadMutVar, tcWriteMutVar,
30 SYN_IE(TcError), SYN_IE(TcWarning),
35 #if __GLASGOW_HASKELL__ >= 200
44 IMPORT_DELOOPER(TcMLoop) ( TcEnv, initEnv, TcMaybe ) -- We need the type TcEnv and an initial Env
46 import Type ( SYN_IE(Type), GenType )
47 import TyVar ( SYN_IE(TyVar), GenTyVar )
48 import Usage ( SYN_IE(Usage), GenUsage )
49 import ErrUtils ( SYN_IE(Error), SYN_IE(Message), SYN_IE(Warning) )
52 import Bag ( Bag, emptyBag, isEmptyBag,
53 foldBag, unitBag, unionBags, snocBag )
54 import FiniteMap ( FiniteMap, emptyFM, isEmptyFM{-, keysFM ToDo:rm-} )
55 import Maybes ( MaybeErr(..) )
56 import SrcLoc ( SrcLoc, noSrcLoc )
57 import UniqFM ( UniqFM, emptyUFM )
58 import UniqSupply ( UniqSupply, getUnique, getUniques, splitUniqSupply )
59 import Unique ( Unique )
62 import PprStyle ( PprStyle(..) )
64 infixr 9 `thenTc`, `thenTc_`, `thenNF_Tc`, `thenNF_Tc_`
68 \section{TcM, NF_TcM: the type checker monads}
69 %~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
72 type NF_TcM s r = TcDown s -> TcEnv s -> SST s r
73 type TcM s r = TcDown s -> TcEnv s -> FSST s r ()
77 #if __GLASGOW_HASKELL__ >= 200
78 # define REAL_WORLD RealWorld
80 # define REAL_WORLD _RealWorld
83 -- With a builtin polymorphic type for runSST the type for
84 -- initTc should use TcM s r instead of TcM RealWorld r
88 -> MaybeErr (r, Bag Warning)
89 (Bag Error, Bag Warning)
93 newMutVarSST us `thenSST` \ us_var ->
94 newMutVarSST (emptyBag,emptyBag) `thenSST` \ errs_var ->
95 newMutVarSST emptyUFM `thenSST` \ tvs_var ->
97 init_down = TcDown [] us_var
100 init_env = initEnv tvs_var
103 (\_ -> returnSST Nothing)
104 (do_this init_down init_env `thenFSST` \ res ->
105 returnFSST (Just res))
106 `thenSST` \ maybe_res ->
107 readMutVarSST errs_var `thenSST` \ (warns,errs) ->
108 case (maybe_res, isEmptyBag errs) of
109 (Just res, True) -> returnSST (Succeeded (res, warns))
110 _ -> returnSST (Failed (errs, warns))
113 thenNF_Tc :: NF_TcM s a
114 -> (a -> TcDown s -> TcEnv s -> State# s -> b)
115 -> TcDown s -> TcEnv s -> State# s -> b
116 -- thenNF_Tc :: NF_TcM s a -> (a -> NF_TcM s b) -> NF_TcM s b
117 -- thenNF_Tc :: NF_TcM s a -> (a -> TcM s b) -> TcM s b
119 thenNF_Tc m k down env
120 = m down env `thenSST` \ r ->
123 thenNF_Tc_ :: NF_TcM s a
124 -> (TcDown s -> TcEnv s -> State# s -> b)
125 -> TcDown s -> TcEnv s -> State# s -> b
126 -- thenNF_Tc :: NF_TcM s a -> NF_TcM s b -> NF_TcM s b
127 -- thenNF_Tc :: NF_TcM s a -> TcM s b -> TcM s b
129 thenNF_Tc_ m k down env
130 = m down env `thenSST_` k down env
132 returnNF_Tc :: a -> NF_TcM s a
133 returnNF_Tc v down env = returnSST v
135 fixNF_Tc :: (a -> NF_TcM s a) -> NF_TcM s a
136 fixNF_Tc m env down = fixSST (\ loop -> m loop env down)
138 mapNF_Tc :: (a -> NF_TcM s b) -> [a] -> NF_TcM s [b]
139 mapNF_Tc f [] = returnNF_Tc []
140 mapNF_Tc f (x:xs) = f x `thenNF_Tc` \ r ->
141 mapNF_Tc f xs `thenNF_Tc` \ rs ->
144 listNF_Tc :: [NF_TcM s a] -> NF_TcM s [a]
145 listNF_Tc [] = returnNF_Tc []
146 listNF_Tc (x:xs) = x `thenNF_Tc` \ r ->
147 listNF_Tc xs `thenNF_Tc` \ rs ->
150 mapBagNF_Tc :: (a -> NF_TcM s b) -> Bag a -> NF_TcM s (Bag b)
152 = foldBag (\ b1 b2 -> b1 `thenNF_Tc` \ r1 ->
153 b2 `thenNF_Tc` \ r2 ->
154 returnNF_Tc (unionBags r1 r2))
155 (\ a -> f a `thenNF_Tc` \ r -> returnNF_Tc (unitBag r))
156 (returnNF_Tc emptyBag)
159 mapAndUnzipNF_Tc :: (a -> NF_TcM s (b,c)) -> [a] -> NF_TcM s ([b],[c])
160 mapAndUnzipNF_Tc f [] = returnNF_Tc ([],[])
161 mapAndUnzipNF_Tc f (x:xs) = f x `thenNF_Tc` \ (r1,r2) ->
162 mapAndUnzipNF_Tc f xs `thenNF_Tc` \ (rs1,rs2) ->
163 returnNF_Tc (r1:rs1, r2:rs2)
165 thenTc :: TcM s a -> (a -> TcM s b) -> TcM s b
167 = m down env `thenFSST` \ r ->
170 thenTc_ :: TcM s a -> TcM s b -> TcM s b
172 = m down env `thenFSST_` k down env
174 returnTc :: a -> TcM s a
175 returnTc val down env = returnFSST val
177 mapTc :: (a -> TcM s b) -> [a] -> TcM s [b]
178 mapTc f [] = returnTc []
179 mapTc f (x:xs) = f x `thenTc` \ r ->
180 mapTc f xs `thenTc` \ rs ->
183 listTc :: [TcM s a] -> TcM s [a]
184 listTc [] = returnTc []
185 listTc (x:xs) = x `thenTc` \ r ->
186 listTc xs `thenTc` \ rs ->
189 foldrTc :: (a -> b -> TcM s b) -> b -> [a] -> TcM s b
190 foldrTc k z [] = returnTc z
191 foldrTc k z (x:xs) = foldrTc k z xs `thenTc` \r ->
194 foldlTc :: (a -> b -> TcM s a) -> a -> [b] -> TcM s a
195 foldlTc k z [] = returnTc z
196 foldlTc k z (x:xs) = k z x `thenTc` \r ->
199 mapAndUnzipTc :: (a -> TcM s (b,c)) -> [a] -> TcM s ([b],[c])
200 mapAndUnzipTc f [] = returnTc ([],[])
201 mapAndUnzipTc f (x:xs) = f x `thenTc` \ (r1,r2) ->
202 mapAndUnzipTc f xs `thenTc` \ (rs1,rs2) ->
203 returnTc (r1:rs1, r2:rs2)
205 mapAndUnzip3Tc :: (a -> TcM s (b,c,d)) -> [a] -> TcM s ([b],[c],[d])
206 mapAndUnzip3Tc f [] = returnTc ([],[],[])
207 mapAndUnzip3Tc f (x:xs) = f x `thenTc` \ (r1,r2,r3) ->
208 mapAndUnzip3Tc f xs `thenTc` \ (rs1,rs2,rs3) ->
209 returnTc (r1:rs1, r2:rs2, r3:rs3)
211 mapBagTc :: (a -> TcM s b) -> Bag a -> TcM s (Bag b)
213 = foldBag (\ b1 b2 -> b1 `thenTc` \ r1 ->
215 returnTc (unionBags r1 r2))
216 (\ a -> f a `thenTc` \ r -> returnTc (unitBag r))
220 fixTc :: (a -> TcM s a) -> TcM s a
221 fixTc m env down = fixFSST (\ loop -> m loop env down)
224 @forkNF_Tc@ runs a sub-typecheck action *lazily* in a separate state
225 thread. Ideally, this elegantly ensures that it can't zap any type
226 variables that belong to the main thread. But alas, the environment
227 contains TyCon and Class environments that include (TcKind s) stuff,
228 which is a Royal Pain. By the time this fork stuff is used they'll
229 have been unified down so there won't be any kind variables, but we
230 can't express that in the current typechecker framework.
232 So we compromise and use unsafeInterleaveSST.
234 We throw away any error messages!
237 forkNF_Tc :: NF_TcM s r -> NF_TcM s r
238 forkNF_Tc m (TcDown deflts u_var src_loc err_cxt err_var) env
239 = -- Get a fresh unique supply
240 readMutVarSST u_var `thenSST` \ us ->
242 (us1, us2) = splitUniqSupply us
244 writeMutVarSST u_var us1 `thenSST_`
246 unsafeInterleaveSST (
247 newMutVarSST us2 `thenSST` \ us_var' ->
248 newMutVarSST (emptyBag,emptyBag) `thenSST` \ err_var' ->
249 newMutVarSST emptyUFM `thenSST` \ tv_var' ->
251 down' = TcDown deflts us_var' src_loc err_cxt err_var'
254 -- ToDo: optionally dump any error messages
262 failTc :: Message -> TcM s a
263 failTc err_msg down env
264 = readMutVarSST errs_var `thenSST` \ (warns,errs) ->
265 listNF_Tc ctxt down env `thenSST` \ ctxt_msgs ->
267 err = mkTcErr loc ctxt_msgs err_msg
269 writeMutVarSST errs_var (warns, errs `snocBag` err) `thenSST_`
272 errs_var = getTcErrs down
273 ctxt = getErrCtxt down
276 warnTc :: Bool -> Message -> NF_TcM s ()
277 warnTc warn_if_true warn down env
278 = if warn_if_true then
279 readMutVarSST errs_var `thenSST` \ (warns,errs) ->
280 writeMutVarSST errs_var (warns `snocBag` warn, errs) `thenSST_`
285 errs_var = getTcErrs down
287 recoverTc :: TcM s r -> TcM s r -> TcM s r
288 recoverTc recover m down env
289 = recoverFSST (\ _ -> recover down env) (m down env)
291 recoverNF_Tc :: NF_TcM s r -> TcM s r -> NF_TcM s r
292 recoverNF_Tc recover m down env
293 = recoverSST (\ _ -> recover down env) (m down env)
295 -- (tryTc r m) tries m; if it succeeds it returns it,
296 -- otherwise it returns r. Any error messages added by m are discarded,
297 -- whether or not m succeeds.
298 tryTc :: TcM s r -> TcM s r -> TcM s r
299 tryTc recover m down env
300 = recoverFSST (\ _ -> recover down env) $
302 newMutVarSST (emptyBag,emptyBag) `thenSST` \ new_errs_var ->
304 m (setTcErrs down new_errs_var) env `thenFSST` \ result ->
306 -- Check that m has no errors; if it has internal recovery
307 -- mechanisms it might "succeed" but having found a bunch of
308 -- errors along the way. If so we want tryTc to use
310 readMutVarSST new_errs_var `thenSST` \ (_,errs) ->
311 if isEmptyBag errs then
316 checkTc :: Bool -> Message -> TcM s () -- Check that the boolean is true
317 checkTc True err = returnTc ()
318 checkTc False err = failTc err
320 checkTcM :: Bool -> TcM s () -> TcM s () -- Check that the boolean is true
321 checkTcM True err = returnTc ()
322 checkTcM False err = err
324 checkMaybeTc :: Maybe val -> Message -> TcM s val
325 checkMaybeTc (Just val) err = returnTc val
326 checkMaybeTc Nothing err = failTc err
328 checkMaybeTcM :: Maybe val -> TcM s val -> TcM s val
329 checkMaybeTcM (Just val) err = returnTc val
330 checkMaybeTcM Nothing err = err
336 tcNewMutVar :: a -> NF_TcM s (MutableVar s a)
337 tcNewMutVar val down env = newMutVarSST val
339 tcWriteMutVar :: MutableVar s a -> a -> NF_TcM s ()
340 tcWriteMutVar var val down env = writeMutVarSST var val
342 tcReadMutVar :: MutableVar s a -> NF_TcM s a
343 tcReadMutVar var down env = readMutVarSST var
350 tcGetEnv :: NF_TcM s (TcEnv s)
351 tcGetEnv down env = returnSST env
353 tcSetEnv :: TcEnv s -> TcM s a -> TcM s a
354 tcSetEnv new_env m down old_env = m down new_env
361 tcGetDefaultTys :: NF_TcM s [Type]
362 tcGetDefaultTys down env = returnSST (getDefaultTys down)
364 tcSetDefaultTys :: [Type] -> TcM s r -> TcM s r
365 tcSetDefaultTys tys m down env = m (setDefaultTys down tys) env
367 tcAddSrcLoc :: SrcLoc -> TcM s a -> TcM s a
368 tcAddSrcLoc loc m down env = m (setLoc down loc) env
370 tcGetSrcLoc :: NF_TcM s SrcLoc
371 tcGetSrcLoc down env = returnSST (getLoc down)
373 tcSetErrCtxtM, tcAddErrCtxtM :: NF_TcM s Message -> TcM s a -> TcM s a
374 tcSetErrCtxtM msg m down env = m (setErrCtxt down msg) env
375 tcAddErrCtxtM msg m down env = m (addErrCtxt down msg) env
377 tcSetErrCtxt, tcAddErrCtxt :: Message -> TcM s a -> TcM s a
378 tcSetErrCtxt msg m down env = m (setErrCtxt down (returnNF_Tc msg)) env
379 tcAddErrCtxt msg m down env = m (addErrCtxt down (returnNF_Tc msg)) env
386 tcGetUnique :: NF_TcM s Unique
388 = readMutVarSST u_var `thenSST` \ uniq_supply ->
390 (new_uniq_supply, uniq_s) = splitUniqSupply uniq_supply
391 uniq = getUnique uniq_s
393 writeMutVarSST u_var new_uniq_supply `thenSST_`
396 u_var = getUniqSupplyVar down
398 tcGetUniques :: Int -> NF_TcM s [Unique]
399 tcGetUniques n down env
400 = readMutVarSST u_var `thenSST` \ uniq_supply ->
402 (new_uniq_supply, uniq_s) = splitUniqSupply uniq_supply
403 uniqs = getUniques n uniq_s
405 writeMutVarSST u_var new_uniq_supply `thenSST_`
408 u_var = getUniqSupplyVar down
418 [Type] -- Types used for defaulting
420 (MutableVar s UniqSupply) -- Unique supply
422 SrcLoc -- Source location
423 (ErrCtxt s) -- Error context
424 (MutableVar s (Bag Warning,
427 type ErrCtxt s = [NF_TcM s Message] -- Innermost first. Monadic so that we have a chance
428 -- to deal with bound type variables just before error
429 -- message construction
432 -- These selectors are *local* to TcMonad.lhs
435 getTcErrs (TcDown def us loc ctxt errs) = errs
436 setTcErrs (TcDown def us loc ctxt _ ) errs = TcDown def us loc ctxt errs
438 getDefaultTys (TcDown def us loc ctxt errs) = def
439 setDefaultTys (TcDown _ us loc ctxt errs) def = TcDown def us loc ctxt errs
441 getLoc (TcDown def us loc ctxt errs) = loc
442 setLoc (TcDown def us _ ctxt errs) loc = TcDown def us loc ctxt errs
444 getUniqSupplyVar (TcDown def us loc ctxt errs) = us
446 setErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc [msg] errs
447 addErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc (msg:ctxt) errs
448 getErrCtxt (TcDown def us loc ctxt errs) = ctxt
458 type TcError = Message
459 type TcWarning = Message
461 mkTcErr :: SrcLoc -- Where
462 -> [Message] -- Context
463 -> Message -- What went wrong
464 -> TcError -- The complete error report
466 mkTcErr locn ctxt msg sty
467 = ppHang (ppBesides [ppr PprForUser locn, ppStr ": ", msg sty])
468 4 (ppAboves [msg sty | msg <- ctxt])
471 arityErr kind name n m sty
472 = ppBesides [ ppStr "`", ppr sty name, ppStr "' should have ",
473 n_arguments, ppStr ", but has been given ", ppInt m, ppChar '.']
475 errmsg = kind ++ " has too " ++ quantity ++ " arguments"
476 quantity | m < n = "few"
478 n_arguments | n == 0 = ppStr "no arguments"
479 | n == 1 = ppStr "1 argument"
480 | True = ppCat [ppInt n, ppStr "arguments"]