X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FdeSugar%2FDsMonad.lhs;h=f24dee4905257e0dbb16c1c0a4f45fc4e697eca0;hb=28a464a75e14cece5db40f2765a29348273ff2d2;hp=9a01390cc9716b66debaeade9f69fa4d1df04f40;hpb=e7d21ee4f8ac907665a7e170c71d59e13a01da09;p=ghc-hetmet.git diff --git a/ghc/compiler/deSugar/DsMonad.lhs b/ghc/compiler/deSugar/DsMonad.lhs index 9a01390..f24dee4 100644 --- a/ghc/compiler/deSugar/DsMonad.lhs +++ b/ghc/compiler/deSugar/DsMonad.lhs @@ -1,309 +1,285 @@ % -% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995 +% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -\section[DesugarMonad]{@DesugarMonad@: monadery used in desugaring} +\section[DsMonad]{@DsMonad@: monadery used in desugaring} \begin{code} -#include "HsVersions.h" - module DsMonad ( - DsM(..), - initDs, returnDs, thenDs, andDs, mapDs, listDs, - mapAndUnzipDs, zipWithDs, - uniqSMtoDsM, - newTyVarsDs, cloneTyVarsDs, - duplicateLocalDs, newSysLocalDs, newSysLocalsDs, + DsM, mappM, mapAndUnzipM, + initDs, returnDs, thenDs, listDs, fixDs, mapAndUnzipDs, + foldlDs, foldrDs, + + newTyVarsDs, newLocalName, + duplicateLocalDs, newSysLocalDs, newSysLocalsDs, newUniqueId, newFailLocalDs, - getSrcLocDs, putSrcLocDs, - getSwitchCheckerDs, ifSwitchSetDs, - getModuleAndGroupDs, - extendEnvDs, lookupEnvDs, lookupEnvWithDefaultDs, - DsIdEnv(..), - lookupId, - - dsShadowError, - DsMatchContext(..), DsMatchKind(..), pprDsWarnings, - -#ifdef DPH - listDs, -#endif - - -- and to make the interface self-sufficient... - Id, DataCon(..), SrcLoc, TyVar, TyVarTemplate, UniType, TauType(..), - ThetaType(..), SigmaType(..), SplitUniqSupply, UniqSM(..), - PlainCoreExpr(..), CoreExpr, GlobalSwitch, SwitchResult - - IF_ATTACK_PRAGMAS(COMMA lookupUFM COMMA lookupIdEnv) - IF_ATTACK_PRAGMAS(COMMA mkIdWithNewUniq COMMA mkSysLocal) - IF_ATTACK_PRAGMAS(COMMA unpackSrcLoc COMMA mkUniqueSupplyGrimily) - IF_ATTACK_PRAGMAS(COMMA mkUniqueGrimily) - IF_ATTACK_PRAGMAS(COMMA splitUniqSupply COMMA getSUnique) + getSrcSpanDs, putSrcSpanDs, + getModuleDs, + newUnique, + UniqSupply, newUniqueSupply, + getDOptsDs, + dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon, dsLookupDataCon, + + DsMetaEnv, DsMetaVal(..), dsLookupMetaEnv, dsExtendMetaEnv, + + -- Warnings + DsWarning, dsWarn, + + -- Data types + DsMatchContext(..), + EquationInfo(..), MatchResult(..), DsWrapper, idWrapper, + CanItFail(..), orFail ) where -import AbsSyn -import AbsUniType ( cloneTyVarFromTemplate, cloneTyVar, - TyVar, TyVarTemplate, UniType, TauType(..), - ThetaType(..), SigmaType(..), Class - IF_ATTACK_PRAGMAS(COMMA cmpTyVar) - ) -import Bag -import CmdLineOpts -- ( GlobalSwitch(..), SwitchResult(..), switchIsOn ) -import Id ( mkIdWithNewUniq, mkSysLocal, Id, DataCon(..) ) -import IdEnv -- ( mkIdEnv, IdEnv ) -import Maybes ( assocMaybe, Maybe(..) ) +#include "HsVersions.h" + +import TcRnMonad +import CoreSyn ( CoreExpr ) +import HsSyn ( HsExpr, HsMatchContext, Pat ) +import TcIface ( tcIfaceGlobal ) +import RdrName ( GlobalRdrEnv ) +import HscTypes ( TyThing(..), TypeEnv, HscEnv, + tyThingId, tyThingTyCon, tyThingDataCon, unQualInScope ) +import Bag ( emptyBag, snocBag, Bag ) +import DataCon ( DataCon ) +import TyCon ( TyCon ) +import Id ( mkSysLocal, setIdUnique, Id ) +import Module ( Module ) +import Var ( TyVar, setTyVarUnique ) import Outputable -import PlainCore -import Pretty -import SrcLoc ( unpackSrcLoc, mkUnknownSrcLoc, SrcLoc ) -import TyVarEnv -- ( nullTyVarEnv, TyVarEnv ) -import SplitUniq -import Unique -import Util +import SrcLoc ( noSrcSpan, SrcSpan ) +import Type ( Type ) +import UniqSupply ( UniqSupply, uniqsFromSupply ) +import Name ( Name, nameOccName ) +import NameEnv +import OccName ( occNameFS ) +import DynFlags ( DynFlags ) +import ErrUtils ( WarnMsg, mkWarnMsg ) +import Bag ( mapBag ) + +import DATA_IOREF ( newIORef, readIORef ) infixr 9 `thenDs` \end{code} +%************************************************************************ +%* * + Data types for the desugarer +%* * +%************************************************************************ + +\begin{code} +data DsMatchContext + = DsMatchContext (HsMatchContext Name) SrcSpan + | NoMatchContext + deriving () + +data EquationInfo + = EqnInfo { eqn_wrap :: DsWrapper, -- Bindings + eqn_pats :: [Pat Id], -- The patterns for an eqn + eqn_rhs :: MatchResult } -- What to do after match + +type DsWrapper = CoreExpr -> CoreExpr +idWrapper e = e + +-- The semantics of (match vs (EqnInfo wrap pats rhs)) is the MatchResult +-- \fail. wrap (case vs of { pats -> rhs fail }) +-- where vs are not bound by wrap + + +-- A MatchResult is an expression with a hole in it +data MatchResult + = MatchResult + CanItFail -- Tells whether the failure expression is used + (CoreExpr -> DsM CoreExpr) + -- Takes a expression to plug in at the + -- failure point(s). The expression should + -- be duplicatable! + +data CanItFail = CanFail | CantFail + +orFail CantFail CantFail = CantFail +orFail _ _ = CanFail +\end{code} + + +%************************************************************************ +%* * + Monad stuff +%* * +%************************************************************************ + Now the mondo monad magic (yes, @DsM@ is a silly name)---carry around a @UniqueSupply@ and some annotations, which presumably include source-file location information: \begin{code} -type DsM result = - SplitUniqSupply - -> SrcLoc -- to put in pattern-matching error msgs - -> (GlobalSwitch -> SwitchResult) -- so we can consult global switches - -> (FAST_STRING, FAST_STRING) -- "module"+"group" : for SCC profiling - -> DsIdEnv - -> DsWarnings - -> (result, DsWarnings) - -type DsWarnings = Bag DsMatchContext -- The desugarer reports matches which are - -- completely shadowed - -#ifdef __GLASGOW_HASKELL__ -{-# INLINE andDs #-} -{-# INLINE thenDs #-} -{-# INLINE returnDs #-} -#endif +type DsM result = TcRnIf DsGblEnv DsLclEnv result + +-- Compatibility functions +fixDs = fixM +thenDs = thenM +returnDs = returnM +listDs = sequenceM +foldlDs = foldlM +foldrDs = foldrM +mapAndUnzipDs = mapAndUnzipM + + +type DsWarning = (SrcSpan, SDoc) + -- Not quite the same as a WarnMsg, we have an SDoc here + -- and we'll do the print_unqual stuff later on to turn it + -- into a Doc. + +data DsGblEnv = DsGblEnv { + ds_mod :: Module, -- For SCC profiling + ds_warns :: IORef (Bag DsWarning), -- Warning messages + ds_if_env :: (IfGblEnv, IfLclEnv) -- Used for looking up global, + -- possibly-imported things + } + +data DsLclEnv = DsLclEnv { + ds_meta :: DsMetaEnv, -- Template Haskell bindings + ds_loc :: SrcSpan -- to put in pattern-matching error msgs + } + +-- Inside [| |] brackets, the desugarer looks +-- up variables in the DsMetaEnv +type DsMetaEnv = NameEnv DsMetaVal + +data DsMetaVal + = Bound Id -- Bound by a pattern inside the [| |]. + -- Will be dynamically alpha renamed. + -- The Id has type THSyntax.Var + + | Splice (HsExpr Id) -- These bindings are introduced by + -- the PendingSplices on a HsBracketOut -- initDs returns the UniqSupply out the end (not just the result) -initDs :: SplitUniqSupply - -> DsIdEnv - -> (GlobalSwitch -> SwitchResult) - -> FAST_STRING -- module name: for profiling; (group name: from switches) +initDs :: HscEnv + -> Module -> GlobalRdrEnv -> TypeEnv -> DsM a - -> (a, DsWarnings) - -initDs init_us env sw_chkr mod_name action - = action init_us mkUnknownSrcLoc sw_chkr module_and_group env emptyBag - where - module_and_group = (mod_name, grp_name) - grp_name = case (stringSwitchSet sw_chkr SccGroup) of - Just xx -> _PK_ xx - Nothing -> mod_name -- default: module name - -thenDs :: DsM a -> (a -> DsM b) -> DsM b -andDs :: (a -> a -> a) -> DsM a -> DsM a -> DsM a - -thenDs expr cont us loc sw_chkr mod_and_grp env warns - = case splitUniqSupply us of { (s1, s2) -> - case (expr s1 loc sw_chkr mod_and_grp env warns) of { (result, warns1) -> - cont result s2 loc sw_chkr mod_and_grp env warns1}} - -andDs combiner m1 m2 us loc sw_chkr mod_and_grp env warns - = case splitUniqSupply us of { (s1, s2) -> - case (m1 s1 loc sw_chkr mod_and_grp env warns) of { (result1, warns1) -> - case (m2 s2 loc sw_chkr mod_and_grp env warns1) of { (result2, warns2) -> - (combiner result1 result2, warns2) }}} - -returnDs :: a -> DsM a -returnDs result us loc sw_chkr mod_and_grp env warns = (result, warns) - -listDs :: [DsM a] -> DsM [a] -listDs [] = returnDs [] -listDs (x:xs) - = x `thenDs` \ r -> - listDs xs `thenDs` \ rs -> - returnDs (r:rs) - -mapDs :: (a -> DsM b) -> [a] -> DsM [b] - -mapDs f [] = returnDs [] -mapDs f (x:xs) - = f x `thenDs` \ r -> - mapDs f xs `thenDs` \ rs -> - returnDs (r:rs) - -mapAndUnzipDs :: (a -> DsM (b, c)) -> [a] -> DsM ([b], [c]) - -mapAndUnzipDs f [] = returnDs ([], []) -mapAndUnzipDs f (x:xs) - = f x `thenDs` \ (r1, r2) -> - mapAndUnzipDs f xs `thenDs` \ (rs1, rs2) -> - returnDs (r1:rs1, r2:rs2) - -zipWithDs :: (a -> b -> DsM c) -> [a] -> [b] -> DsM [c] - -zipWithDs f [] [] = returnDs [] -zipWithDs f (x:xs) (y:ys) - = f x y `thenDs` \ r -> - zipWithDs f xs ys `thenDs` \ rs -> - returnDs (r:rs) + -> IO (a, Bag WarnMsg) + +initDs hsc_env mod rdr_env type_env thing_inside + = do { warn_var <- newIORef emptyBag + ; let { if_genv = IfGblEnv { if_rec_types = Just (mod, return type_env) } + ; if_lenv = mkIfLclEnv mod (ptext SLIT("GHC error in desugarer lookup in") <+> ppr mod) + ; gbl_env = DsGblEnv { ds_mod = mod, + ds_if_env = (if_genv, if_lenv), + ds_warns = warn_var } + ; lcl_env = DsLclEnv { ds_meta = emptyNameEnv, + ds_loc = noSrcSpan } } + + ; res <- initTcRnIf 'd' hsc_env gbl_env lcl_env thing_inside + + ; warns <- readIORef warn_var + ; return (res, mapBag mk_warn warns) + } + where + print_unqual = unQualInScope rdr_env + + mk_warn :: (SrcSpan,SDoc) -> WarnMsg + mk_warn (loc,sdoc) = mkWarnMsg loc print_unqual sdoc \end{code} +%************************************************************************ +%* * + Operations in the monad +%* * +%************************************************************************ + And all this mysterious stuff is so we can occasionally reach out and grab one or more names. @newLocalDs@ isn't exported---exported functions are defined with it. The difference in name-strings makes it easier to read debugging output. -\begin{code} -newLocalDs :: FAST_STRING -> UniType -> DsM Id -newLocalDs nm ty us loc sw_chkr mod_and_grp env warns - = case (getSUnique us) of { assigned_uniq -> - (mkSysLocal nm assigned_uniq ty loc, warns) } -newSysLocalDs = newLocalDs SLIT("ds") -newSysLocalsDs tys = mapDs (newLocalDs SLIT("ds")) tys -newFailLocalDs = newLocalDs SLIT("fail") +\begin{code} +-- Make a new Id with the same print name, but different type, and new unique +newUniqueId :: Name -> Type -> DsM Id +newUniqueId id ty + = newUnique `thenDs` \ uniq -> + returnDs (mkSysLocal (occNameFS (nameOccName id)) uniq ty) duplicateLocalDs :: Id -> DsM Id -duplicateLocalDs old_local us loc sw_chkr mod_and_grp env warns - = case (getSUnique us) of { assigned_uniq -> - (mkIdWithNewUniq old_local assigned_uniq, warns) } - -cloneTyVarsDs :: [TyVar] -> DsM [TyVar] -cloneTyVarsDs tyvars us loc sw_chkr mod_and_grp env warns - = case (getSUniques (length tyvars) us) of { uniqs -> - (zipWith cloneTyVar tyvars uniqs, warns) } -\end{code} +duplicateLocalDs old_local + = newUnique `thenDs` \ uniq -> + returnDs (setIdUnique old_local uniq) -\begin{code} -newTyVarsDs :: [TyVarTemplate] -> DsM [TyVar] +newSysLocalDs, newFailLocalDs :: Type -> DsM Id +newSysLocalDs ty + = newUnique `thenDs` \ uniq -> + returnDs (mkSysLocal FSLIT("ds") uniq ty) + +newSysLocalsDs tys = mappM newSysLocalDs tys -newTyVarsDs tyvar_tmpls us loc sw_chkr mod_and_grp env warns - = case (getSUniques (length tyvar_tmpls) us) of { uniqs -> - (zipWith cloneTyVarFromTemplate tyvar_tmpls uniqs, warns) } +newFailLocalDs ty + = newUnique `thenDs` \ uniq -> + returnDs (mkSysLocal FSLIT("fail") uniq ty) + -- The UserLocal bit just helps make the code a little clearer \end{code} -We can also reach out and either set/grab location information from -the @SrcLoc@ being carried around. \begin{code} -uniqSMtoDsM :: UniqSM a -> DsM a - -uniqSMtoDsM u_action us loc sw_chkr mod_and_grp env warns - = let - us_to_use = mkUniqueSupplyGrimily us - in - (snd (u_action us_to_use), warns) - -getSrcLocDs :: DsM (String, String) -getSrcLocDs us loc sw_chkr mod_and_grp env warns - = case (unpackSrcLoc loc) of { (x,y) -> - ((_UNPK_ x, _UNPK_ y), warns) } - -putSrcLocDs :: SrcLoc -> DsM a -> DsM a -putSrcLocDs new_loc expr us old_loc sw_chkr mod_and_grp env warns - = expr us new_loc sw_chkr mod_and_grp env warns - -dsShadowError :: DsMatchContext -> DsM () -dsShadowError cxt us loc sw_chkr mod_and_grp env warns - = ((), warns `snocBag` cxt) +newTyVarsDs :: [TyVar] -> DsM [TyVar] +newTyVarsDs tyvar_tmpls + = newUniqueSupply `thenDs` \ uniqs -> + returnDs (zipWith setTyVarUnique tyvar_tmpls (uniqsFromSupply uniqs)) \end{code} +We can also reach out and either set/grab location information from +the @SrcSpan@ being carried around. + \begin{code} -getSwitchCheckerDs :: DsM (GlobalSwitch -> Bool) -getSwitchCheckerDs us loc sw_chkr mod_and_grp env warns - = (switchIsOn sw_chkr, warns) - -ifSwitchSetDs :: GlobalSwitch -> DsM a -> DsM a -> DsM a -ifSwitchSetDs switch then_ else_ us loc sw_chkr mod_and_grp env warns - = (if switchIsOn sw_chkr switch then then_ else else_) - us loc sw_chkr mod_and_grp env warns - -getModuleAndGroupDs :: DsM (FAST_STRING, FAST_STRING) -getModuleAndGroupDs us loc sw_chkr mod_and_grp env warns - = (mod_and_grp, warns) +getDOptsDs :: DsM DynFlags +getDOptsDs = getDOpts + +getModuleDs :: DsM Module +getModuleDs = do { env <- getGblEnv; return (ds_mod env) } + +getSrcSpanDs :: DsM SrcSpan +getSrcSpanDs = do { env <- getLclEnv; return (ds_loc env) } + +putSrcSpanDs :: SrcSpan -> DsM a -> DsM a +putSrcSpanDs new_loc thing_inside = updLclEnv (\ env -> env {ds_loc = new_loc}) thing_inside + +dsWarn :: SDoc -> DsM () +dsWarn warn = do { env <- getGblEnv + ; loc <- getSrcSpanDs + ; updMutVar (ds_warns env) (`snocBag` (loc,msg)) } + where + msg = ptext SLIT("Warning:") <+> warn \end{code} \begin{code} -type DsIdEnv = IdEnv PlainCoreExpr - -extendEnvDs :: [(Id, PlainCoreExpr)] -> DsM a -> DsM a - -extendEnvDs pairs expr us loc sw_chkr mod_and_grp old_env warns - = case splitUniqSupply us of { (s1, s2) -> - case (mapAccumL subst s1 pairs) of { (_, revised_pairs) -> - expr s2 loc sw_chkr mod_and_grp (growIdEnvList old_env revised_pairs) warns - }} - where - subst us (v, expr) - = case splitUniqSupply us of { (s1, s2) -> - let - us_to_use = mkUniqueSupplyGrimily s1 - in - case (substCoreExpr us_to_use old_env nullTyVarEnv expr) of { (_, expr2) -> - (s2, (v, expr2)) }} - -lookupEnvDs :: Id -> DsM (Maybe PlainCoreExpr) -lookupEnvDs id us loc sw_chkr mod_and_grp env warns - = (lookupIdEnv env id, warns) - -- Note: we don't assert anything about the Id - -- being looked up. There's not really anything - -- much to say about it. (WDP 94/06) - -lookupEnvWithDefaultDs :: Id -> PlainCoreExpr -> DsM PlainCoreExpr -lookupEnvWithDefaultDs id deflt us loc sw_chkr mod_and_grp env warns - = (case (lookupIdEnv env id) of - Nothing -> deflt - Just xx -> xx, - warns) - -lookupId :: [(Id, a)] -> Id -> a -lookupId env id - = assoc "lookupId" env id +dsLookupGlobal :: Name -> DsM TyThing +-- Very like TcEnv.tcLookupGlobal +dsLookupGlobal name + = do { env <- getGblEnv + ; setEnvs (ds_if_env env) + (tcIfaceGlobal name) } + +dsLookupGlobalId :: Name -> DsM Id +dsLookupGlobalId name + = dsLookupGlobal name `thenDs` \ thing -> + returnDs (tyThingId thing) + +dsLookupTyCon :: Name -> DsM TyCon +dsLookupTyCon name + = dsLookupGlobal name `thenDs` \ thing -> + returnDs (tyThingTyCon thing) + +dsLookupDataCon :: Name -> DsM DataCon +dsLookupDataCon name + = dsLookupGlobal name `thenDs` \ thing -> + returnDs (tyThingDataCon thing) \end{code} -%************************************************************************ -%* * -%* type synonym EquationInfo and access functions for its pieces * -%* * -%************************************************************************ - \begin{code} -data DsMatchContext - = DsMatchContext DsMatchKind [TypecheckedPat] SrcLoc - | NoMatchContext +dsLookupMetaEnv :: Name -> DsM (Maybe DsMetaVal) +dsLookupMetaEnv name = do { env <- getLclEnv; return (lookupNameEnv (ds_meta env) name) } -data DsMatchKind - = FunMatch Id - | CaseMatch - | LambdaMatch - | PatBindMatch - -pprDsWarnings :: PprStyle -> Bag DsMatchContext -> Pretty -pprDsWarnings sty warns - = ppAboves (map pp_cxt (bagToList warns)) - where - pp_cxt NoMatchContext = ppPStr SLIT("Some match is shadowed; I don't know what") - pp_cxt (DsMatchContext kind pats loc) - = ppHang (ppBesides [ppr PprForUser loc, ppPStr SLIT(": ")]) - 4 (ppHang (ppPStr SLIT("Pattern match(es) completely overlapped:")) - 4 (pp_match kind pats)) - - pp_match (FunMatch fun) pats - = ppHang (ppr sty fun) - 4 (ppSep [ppSep (map (ppr sty) pats), ppPStr SLIT("= ...")]) - - pp_match CaseMatch pats - = ppHang (ppPStr SLIT("in a case alternative:")) - 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot]) - - pp_match PatBindMatch pats - = ppHang (ppPStr SLIT("in a pattern binding:")) - 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot]) - - pp_match LambdaMatch pats - = ppHang (ppPStr SLIT("in a lambda abstraction:")) - 4 (ppSep [ppSep (map (ppr sty) pats), pp_arrow_dotdotdot]) - - pp_arrow_dotdotdot = ppPStr SLIT("-> ...") +dsExtendMetaEnv :: DsMetaEnv -> DsM a -> DsM a +dsExtendMetaEnv menv thing_inside + = updLclEnv (\env -> env { ds_meta = ds_meta env `plusNameEnv` menv }) thing_inside \end{code} + +