\begin{code}
-#include "HsVersions.h"
-
module TcMonad(
- SYN_IE(TcM), SYN_IE(NF_TcM), TcDown, TcEnv,
+ TcM, NF_TcM, TcDown, TcEnv,
SST_R, FSST_R,
initTc,
uniqSMToTcM,
- returnNF_Tc, thenNF_Tc, thenNF_Tc_, mapNF_Tc, fixNF_Tc, forkNF_Tc,
+ returnNF_Tc, thenNF_Tc, thenNF_Tc_, mapNF_Tc,
+ fixNF_Tc, forkNF_Tc, foldrNF_Tc, foldlNF_Tc,
listNF_Tc, mapAndUnzipNF_Tc, mapBagNF_Tc,
checkTc, checkTcM, checkMaybeTc, checkMaybeTcM,
- failTc, warnTc, recoverTc, checkNoErrsTc, recoverNF_Tc, discardErrsTc,
+ failTc, failWithTc, addErrTc, warnTc, recoverTc, checkNoErrsTc, recoverNF_Tc, discardErrsTc,
tcGetEnv, tcSetEnv,
tcGetDefaultTys, tcSetDefaultTys,
tcAddErrCtxtM, tcSetErrCtxtM,
tcAddErrCtxt, tcSetErrCtxt,
- tcNewMutVar, tcReadMutVar, tcWriteMutVar,
-
- SYN_IE(TcError), SYN_IE(TcWarning),
- mkTcErr, arityErr,
+ tcNewMutVar, tcReadMutVar, tcWriteMutVar, TcRef,
- -- For closure
- SYN_IE(MutableVar),
-#if __GLASGOW_HASKELL__ == 201
- GHCbase.MutableArray
-#elif __GLASGOW_HASKELL__ == 201
- GlaExts.MutableArray
-#else
- _MutableArray
-#endif
+ TcError, TcWarning,
+ arityErr
) where
-IMP_Ubiq(){-uitous-}
+#include "HsVersions.h"
-#if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
-IMPORT_DELOOPER(TcMLoop) ( TcEnv, initEnv, TcMaybe ) -- We need the type TcEnv and an initial Env
-#else
-import {-# SOURCE #-} TcEnv ( TcEnv, initEnv )
-import {-# SOURCE #-} TcType ( TcMaybe, TcTyVarSet )
-#endif
+import {-# SOURCE #-} TcEnv ( TcEnv )
-import Type ( SYN_IE(Type), GenType )
-import TyVar ( SYN_IE(TyVar), GenTyVar )
-import Usage ( SYN_IE(Usage), GenUsage )
-import ErrUtils ( SYN_IE(Error), SYN_IE(Message), SYN_IE(Warning) )
-import CmdLineOpts ( opt_PprStyle_All, opt_PprUserLength )
+import Type ( Type, GenType )
+import ErrUtils ( addShortErrLocLine, addShortWarnLocLine, ErrMsg, Message, WarnMsg )
+import CmdLineOpts ( opt_PprStyle_All )
import SST
import Bag ( Bag, emptyBag, isEmptyBag,
foldBag, unitBag, unionBags, snocBag )
-import FiniteMap ( FiniteMap, emptyFM, isEmptyFM{-, keysFM ToDo:rm-} )
-import Maybes ( MaybeErr(..) )
import SrcLoc ( SrcLoc, noSrcLoc )
import UniqFM ( UniqFM, emptyUFM )
import UniqSupply ( UniqSupply, getUnique, getUniques, splitUniqSupply,
- SYN_IE(UniqSM), initUs )
+ UniqSM, initUs )
import Unique ( Unique )
import Util
-import Pretty
-import Outputable ( PprStyle(..), Outputable(..) )
+import Outputable
+
+import GlaExts ( State#, RealWorld )
infixr 9 `thenTc`, `thenTc_`, `thenNF_Tc`, `thenNF_Tc_`
\end{code}
\begin{code}
-#if __GLASGOW_HASKELL__ >= 200
-# define REAL_WORLD RealWorld
-#else
-# define REAL_WORLD _RealWorld
-#endif
-
-- With a builtin polymorphic type for runSST the type for
-- initTc should use TcM s r instead of TcM RealWorld r
+-- initEnv is passed in to avoid module recursion between TcEnv & TcMonad.
+
initTc :: UniqSupply
- -> TcM REAL_WORLD r
- -> MaybeErr (r, Bag Warning)
- (Bag Error, Bag Warning)
+ -> (TcRef RealWorld (UniqFM a) -> TcEnv RealWorld)
+ -> TcM RealWorld r
+ -> (Maybe r, Bag WarnMsg, Bag ErrMsg)
-initTc us do_this
+initTc us initenv do_this
= runSST (
newMutVarSST us `thenSST` \ us_var ->
newMutVarSST (emptyBag,emptyBag) `thenSST` \ errs_var ->
init_down = TcDown [] us_var
noSrcLoc
[] errs_var
- init_env = initEnv tvs_var
+ init_env = initenv tvs_var
in
recoverSST
(\_ -> returnSST Nothing)
returnFSST (Just res))
`thenSST` \ maybe_res ->
readMutVarSST errs_var `thenSST` \ (warns,errs) ->
- case (maybe_res, isEmptyBag errs) of
- (Just res, True) -> returnSST (Succeeded (res, warns))
- _ -> returnSST (Failed (errs, warns))
+ returnSST (maybe_res, warns, errs)
)
thenNF_Tc :: NF_TcM s a
mapNF_Tc f xs `thenNF_Tc` \ rs ->
returnNF_Tc (r:rs)
+foldrNF_Tc :: (a -> b -> NF_TcM s b) -> b -> [a] -> NF_TcM s b
+foldrNF_Tc k z [] = returnNF_Tc z
+foldrNF_Tc k z (x:xs) = foldrNF_Tc k z xs `thenNF_Tc` \r ->
+ k x r
+
+foldlNF_Tc :: (a -> b -> NF_TcM s a) -> a -> [b] -> NF_TcM s a
+foldlNF_Tc k z [] = returnNF_Tc z
+foldlNF_Tc k z (x:xs) = k z x `thenNF_Tc` \r ->
+ foldlNF_Tc k r xs
+
listNF_Tc :: [NF_TcM s a] -> NF_TcM s [a]
listNF_Tc [] = returnNF_Tc []
listNF_Tc (x:xs) = x `thenNF_Tc` \ r ->
Error handling
~~~~~~~~~~~~~~
\begin{code}
-getErrsTc :: NF_TcM s (Bag Error, Bag Warning)
+getErrsTc :: NF_TcM s (Bag ErrMsg, Bag WarnMsg)
getErrsTc down env
= readMutVarSST errs_var
where
errs_var = getTcErrs down
-failTc :: Message -> TcM s a
-failTc err_msg down env
+
+failTc :: TcM s a
+failTc down env
+ = failFSST ()
+
+failWithTc :: Message -> TcM s a -- Add an error message and fail
+failWithTc err_msg
+ = addErrTc err_msg `thenNF_Tc_`
+ failTc
+
+addErrTc :: Message -> NF_TcM s () -- Add an error message but don't fail
+addErrTc err_msg down env
= readMutVarSST errs_var `thenSST` \ (warns,errs) ->
listNF_Tc ctxt down env `thenSST` \ ctxt_msgs ->
let
- err = mkTcErr loc ctxt_msgs err_msg
+ err = addShortErrLocLine loc $
+ vcat (err_msg : ctxt_to_use ctxt_msgs)
in
writeMutVarSST errs_var (warns, errs `snocBag` err) `thenSST_`
- failFSST ()
+ returnSST ()
where
errs_var = getTcErrs down
ctxt = getErrCtxt down
loc = getLoc down
warnTc :: Bool -> Message -> NF_TcM s ()
-warnTc warn_if_true warn down env
+warnTc warn_if_true warn_msg down env
= if warn_if_true then
- readMutVarSST errs_var `thenSST` \ (warns,errs) ->
+ readMutVarSST errs_var `thenSST` \ (warns,errs) ->
listNF_Tc ctxt down env `thenSST` \ ctxt_msgs ->
let
- full_warn = mkTcErr loc ctxt_msgs warn
+ warn = addShortWarnLocLine loc $
+ vcat (warn_msg : ctxt_to_use ctxt_msgs)
in
- writeMutVarSST errs_var (warns `snocBag` full_warn, errs) `thenSST_`
+ writeMutVarSST errs_var (warns `snocBag` warn, errs) `thenSST_`
returnSST ()
else
returnSST ()
= newMutVarSST (emptyBag,emptyBag) `thenSST` \ m_errs_var ->
let
errs_var = getTcErrs down
- propagate_errs
+ propagate_errs _
= readMutVarSST m_errs_var `thenSST` \ (m_warns, m_errs) ->
readMutVarSST errs_var `thenSST` \ (warns, errs) ->
writeMutVarSST errs_var (warns `unionBags` m_warns,
errs `unionBags` m_errs) `thenSST_`
- returnSST m_errs
+ failFSST()
in
- recoverFSST (\ _ -> propagate_errs `thenSST_` failFSST ()) $
+ recoverFSST propagate_errs $
m (setTcErrs down m_errs_var) env `thenFSST` \ result ->
-- Check that m has no errors; if it has internal recovery
-- mechanisms it might "succeed" but having found a bunch of
-- errors along the way.
- propagate_errs `thenSST` \ errs ->
- if isEmptyBag errs then
+ readMutVarSST m_errs_var `thenSST` \ (m_warns, m_errs) ->
+ if isEmptyBag m_errs then
returnFSST result
else
- failFSST ()
+ failFSST () -- This triggers the recoverFSST
-- (tryTc r m) tries m; if it succeeds it returns it,
-- otherwise it returns r. Any error messages added by m are discarded,
recover down env
-- Run the thing inside, but throw away all its error messages.
-discardErrsTc :: TcM s r -> TcM s r
+-- discardErrsTc :: TcM s r -> TcM s r
+-- discardErrsTc :: NF_TcM s r -> NF_TcM s r
+discardErrsTc :: (TcDown s -> TcEnv s -> State# s -> a)
+ -> (TcDown s -> TcEnv s -> State# s -> a)
discardErrsTc m down env
= newMutVarSST (emptyBag,emptyBag) `thenSST` \ new_errs_var ->
m (setTcErrs down new_errs_var) env
checkTc :: Bool -> Message -> TcM s () -- Check that the boolean is true
checkTc True err = returnTc ()
-checkTc False err = failTc err
+checkTc False err = failWithTc err
checkTcM :: Bool -> TcM s () -> TcM s () -- Check that the boolean is true
checkTcM True err = returnTc ()
checkMaybeTc :: Maybe val -> Message -> TcM s val
checkMaybeTc (Just val) err = returnTc val
-checkMaybeTc Nothing err = failTc err
+checkMaybeTc Nothing err = failWithTc err
checkMaybeTcM :: Maybe val -> TcM s val -> TcM s val
checkMaybeTcM (Just val) err = returnTc val
Mutable variables
~~~~~~~~~~~~~~~~~
\begin{code}
-tcNewMutVar :: a -> NF_TcM s (MutableVar s a)
+type TcRef s a = SSTRef s a
+
+tcNewMutVar :: a -> NF_TcM s (TcRef s a)
tcNewMutVar val down env = newMutVarSST val
-tcWriteMutVar :: MutableVar s a -> a -> NF_TcM s ()
+tcWriteMutVar :: TcRef s a -> a -> NF_TcM s ()
tcWriteMutVar var val down env = writeMutVarSST var val
-tcReadMutVar :: MutableVar s a -> NF_TcM s a
+tcReadMutVar :: TcRef s a -> NF_TcM s a
tcReadMutVar var down env = readMutVarSST var
\end{code}
tcSetEnv :: TcEnv s
-> (TcDown s -> TcEnv s -> State# s -> b)
- -> TcDown s -> TcEnv s -> State# s -> b
+ -> TcDown s -> TcEnv s -> State# s -> b
-- tcSetEnv :: TcEnv s -> TcM s a -> TcM s a
-- tcSetEnv :: TcEnv s -> NF_TcM s a -> NF_TcM s a
tcSetDefaultTys :: [Type] -> TcM s r -> TcM s r
tcSetDefaultTys tys m down env = m (setDefaultTys down tys) env
-tcAddSrcLoc :: SrcLoc -> TcM s a -> TcM s a
+-- tcAddSrcLoc :: SrcLoc -> TcM s a -> TcM s a
+-- tcAddSrcLoc :: SrcLoc -> NF_TcM s a -> NF_TcM s a
+tcAddSrcLoc :: SrcLoc -> (TcDown s -> env -> result)
+ -> (TcDown s -> env -> result)
tcAddSrcLoc loc m down env = m (setLoc down loc) env
tcGetSrcLoc :: NF_TcM s SrcLoc
tcSetErrCtxtM msg m down env = m (setErrCtxt down msg) env
tcAddErrCtxtM msg m down env = m (addErrCtxt down msg) env
-tcSetErrCtxt, tcAddErrCtxt :: Message -> TcM s a -> TcM s a
+tcSetErrCtxt, tcAddErrCtxt
+ :: Message
+ -> (TcDown s -> TcEnv s -> State# s -> b)
+ -> TcDown s -> TcEnv s -> State# s -> b
+-- Usual thing
tcSetErrCtxt msg m down env = m (setErrCtxt down (returnNF_Tc msg)) env
tcAddErrCtxt msg m down env = m (addErrCtxt down (returnNF_Tc msg)) env
\end{code}
= TcDown
[Type] -- Types used for defaulting
- (MutableVar s UniqSupply) -- Unique supply
+ (TcRef s UniqSupply) -- Unique supply
SrcLoc -- Source location
(ErrCtxt s) -- Error context
- (MutableVar s (Bag Warning,
- Bag Error))
+ (TcRef s (Bag WarnMsg,
+ Bag ErrMsg))
type ErrCtxt s = [NF_TcM s Message] -- Innermost first. Monadic so that we have a chance
-- to deal with bound type variables just before error
type TcError = Message
type TcWarning = Message
-mkTcErr :: SrcLoc -- Where
- -> [Message] -- Context
- -> Message -- What went wrong
- -> TcError -- The complete error report
+ctxt_to_use ctxt | opt_PprStyle_All = ctxt
+ | otherwise = takeAtMost 3 ctxt
+ where
+ takeAtMost :: Int -> [a] -> [a]
+ takeAtMost 0 ls = []
+ takeAtMost n [] = []
+ takeAtMost n (x:xs) = x:takeAtMost (n-1) xs
-mkTcErr locn ctxt msg sty
- = hang (hcat [ppr (PprForUser opt_PprUserLength) locn, ptext SLIT(": "), msg sty])
- 4 (vcat [msg sty | msg <- ctxt_to_use])
- where
- ctxt_to_use =
- if opt_PprStyle_All then
- ctxt
- else
- takeAtMost 4 ctxt
-
- takeAtMost :: Int -> [a] -> [a]
- takeAtMost 0 ls = []
- takeAtMost n [] = []
- takeAtMost n (x:xs) = x:takeAtMost (n-1) xs
-
-arityErr kind name n m sty
- = hsep [ ppr sty name, ptext SLIT("should have"),
+arityErr kind name n m
+ = hsep [ ppr name, ptext SLIT("should have"),
n_arguments <> comma, text "but has been given", int m, char '.']
where
- errmsg = kind ++ " has too " ++ quantity ++ " arguments"
- quantity | m < n = "few"
- | otherwise = "many"
n_arguments | n == 0 = ptext SLIT("no arguments")
| n == 1 = ptext SLIT("1 argument")
| True = hsep [int n, ptext SLIT("arguments")]