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, getErrsTc,
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 getErrsTc :: NF_TcM s (Bag Error, Bag Warning)
264 = readMutVarSST errs_var
266 errs_var = getTcErrs down
268 failTc :: Message -> TcM s a
269 failTc err_msg down env
270 = readMutVarSST errs_var `thenSST` \ (warns,errs) ->
271 listNF_Tc ctxt down env `thenSST` \ ctxt_msgs ->
273 err = mkTcErr loc ctxt_msgs err_msg
275 writeMutVarSST errs_var (warns, errs `snocBag` err) `thenSST_`
278 errs_var = getTcErrs down
279 ctxt = getErrCtxt down
282 warnTc :: Bool -> Message -> NF_TcM s ()
283 warnTc warn_if_true warn down env
284 = if warn_if_true then
285 readMutVarSST errs_var `thenSST` \ (warns,errs) ->
286 writeMutVarSST errs_var (warns `snocBag` warn, errs) `thenSST_`
291 errs_var = getTcErrs down
293 recoverTc :: TcM s r -> TcM s r -> TcM s r
294 recoverTc recover m down env
295 = recoverFSST (\ _ -> recover down env) (m down env)
297 recoverNF_Tc :: NF_TcM s r -> TcM s r -> NF_TcM s r
298 recoverNF_Tc recover m down env
299 = recoverSST (\ _ -> recover down env) (m down env)
301 -- (tryTc r m) tries m; if it succeeds it returns it,
302 -- otherwise it returns r. Any error messages added by m are discarded,
303 -- whether or not m succeeds.
304 tryTc :: TcM s r -> TcM s r -> TcM s r
305 tryTc recover m down env
306 = recoverFSST (\ _ -> recover down env) $
308 newMutVarSST (emptyBag,emptyBag) `thenSST` \ new_errs_var ->
310 m (setTcErrs down new_errs_var) env `thenFSST` \ result ->
312 -- Check that m has no errors; if it has internal recovery
313 -- mechanisms it might "succeed" but having found a bunch of
314 -- errors along the way. If so we want tryTc to use
316 readMutVarSST new_errs_var `thenSST` \ (_,errs) ->
317 if isEmptyBag errs then
322 checkTc :: Bool -> Message -> TcM s () -- Check that the boolean is true
323 checkTc True err = returnTc ()
324 checkTc False err = failTc err
326 checkTcM :: Bool -> TcM s () -> TcM s () -- Check that the boolean is true
327 checkTcM True err = returnTc ()
328 checkTcM False err = err
330 checkMaybeTc :: Maybe val -> Message -> TcM s val
331 checkMaybeTc (Just val) err = returnTc val
332 checkMaybeTc Nothing err = failTc err
334 checkMaybeTcM :: Maybe val -> TcM s val -> TcM s val
335 checkMaybeTcM (Just val) err = returnTc val
336 checkMaybeTcM Nothing err = err
342 tcNewMutVar :: a -> NF_TcM s (MutableVar s a)
343 tcNewMutVar val down env = newMutVarSST val
345 tcWriteMutVar :: MutableVar s a -> a -> NF_TcM s ()
346 tcWriteMutVar var val down env = writeMutVarSST var val
348 tcReadMutVar :: MutableVar s a -> NF_TcM s a
349 tcReadMutVar var down env = readMutVarSST var
356 tcGetEnv :: NF_TcM s (TcEnv s)
357 tcGetEnv down env = returnSST env
359 tcSetEnv :: TcEnv s -> TcM s a -> TcM s a
360 tcSetEnv new_env m down old_env = m down new_env
367 tcGetDefaultTys :: NF_TcM s [Type]
368 tcGetDefaultTys down env = returnSST (getDefaultTys down)
370 tcSetDefaultTys :: [Type] -> TcM s r -> TcM s r
371 tcSetDefaultTys tys m down env = m (setDefaultTys down tys) env
373 tcAddSrcLoc :: SrcLoc -> TcM s a -> TcM s a
374 tcAddSrcLoc loc m down env = m (setLoc down loc) env
376 tcGetSrcLoc :: NF_TcM s SrcLoc
377 tcGetSrcLoc down env = returnSST (getLoc down)
379 tcSetErrCtxtM, tcAddErrCtxtM :: NF_TcM s Message -> TcM s a -> TcM s a
380 tcSetErrCtxtM msg m down env = m (setErrCtxt down msg) env
381 tcAddErrCtxtM msg m down env = m (addErrCtxt down msg) env
383 tcSetErrCtxt, tcAddErrCtxt :: Message -> TcM s a -> TcM s a
384 tcSetErrCtxt msg m down env = m (setErrCtxt down (returnNF_Tc msg)) env
385 tcAddErrCtxt msg m down env = m (addErrCtxt down (returnNF_Tc msg)) env
392 tcGetUnique :: NF_TcM s Unique
394 = readMutVarSST u_var `thenSST` \ uniq_supply ->
396 (new_uniq_supply, uniq_s) = splitUniqSupply uniq_supply
397 uniq = getUnique uniq_s
399 writeMutVarSST u_var new_uniq_supply `thenSST_`
402 u_var = getUniqSupplyVar down
404 tcGetUniques :: Int -> NF_TcM s [Unique]
405 tcGetUniques n down env
406 = readMutVarSST u_var `thenSST` \ uniq_supply ->
408 (new_uniq_supply, uniq_s) = splitUniqSupply uniq_supply
409 uniqs = getUniques n uniq_s
411 writeMutVarSST u_var new_uniq_supply `thenSST_`
414 u_var = getUniqSupplyVar down
424 [Type] -- Types used for defaulting
426 (MutableVar s UniqSupply) -- Unique supply
428 SrcLoc -- Source location
429 (ErrCtxt s) -- Error context
430 (MutableVar s (Bag Warning,
433 type ErrCtxt s = [NF_TcM s Message] -- Innermost first. Monadic so that we have a chance
434 -- to deal with bound type variables just before error
435 -- message construction
438 -- These selectors are *local* to TcMonad.lhs
441 getTcErrs (TcDown def us loc ctxt errs) = errs
442 setTcErrs (TcDown def us loc ctxt _ ) errs = TcDown def us loc ctxt errs
444 getDefaultTys (TcDown def us loc ctxt errs) = def
445 setDefaultTys (TcDown _ us loc ctxt errs) def = TcDown def us loc ctxt errs
447 getLoc (TcDown def us loc ctxt errs) = loc
448 setLoc (TcDown def us _ ctxt errs) loc = TcDown def us loc ctxt errs
450 getUniqSupplyVar (TcDown def us loc ctxt errs) = us
452 setErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc [msg] errs
453 addErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc (msg:ctxt) errs
454 getErrCtxt (TcDown def us loc ctxt errs) = ctxt
464 type TcError = Message
465 type TcWarning = Message
467 mkTcErr :: SrcLoc -- Where
468 -> [Message] -- Context
469 -> Message -- What went wrong
470 -> TcError -- The complete error report
472 mkTcErr locn ctxt msg sty
473 = ppHang (ppBesides [ppr PprForUser locn, ppStr ": ", msg sty])
474 4 (ppAboves [msg sty | msg <- ctxt])
477 arityErr kind name n m sty
478 = ppBesides [ ppStr "`", ppr sty name, ppStr "' should have ",
479 n_arguments, ppStr ", but has been given ", ppInt m, ppChar '.']
481 errmsg = kind ++ " has too " ++ quantity ++ " arguments"
482 quantity | m < n = "few"
484 n_arguments | n == 0 = ppStr "no arguments"
485 | n == 1 = ppStr "1 argument"
486 | True = ppCat [ppInt n, ppStr "arguments"]