Re-working of the breakpoint support
[ghc-hetmet.git] / compiler / deSugar / DsMonad.lhs
index f24dee4..ac6a0c0 100644 (file)
@@ -1,12 +1,14 @@
 %
+% (c) The University of Glasgow 2006
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-\section[DsMonad]{@DsMonad@: monadery used in desugaring}
+
+@DsMonad@: monadery used in desugaring
 
 \begin{code}
 module DsMonad (
        DsM, mappM, mapAndUnzipM,
-       initDs, returnDs, thenDs, listDs, fixDs, mapAndUnzipDs, 
+       initDs, initDsTc, returnDs, thenDs, listDs, fixDs, mapAndUnzipDs, 
        foldlDs, foldrDs,
 
        newTyVarsDs, newLocalName,
@@ -16,47 +18,48 @@ module DsMonad (
        getModuleDs,
        newUnique, 
        UniqSupply, newUniqueSupply,
-       getDOptsDs,
+       getDOptsDs, getGhcModeDs, doptDs,
        dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon, dsLookupDataCon,
 
        DsMetaEnv, DsMetaVal(..), dsLookupMetaEnv, dsExtendMetaEnv,
 
+        bindLocalsDs, getLocalBindsDs,
        -- Warnings
-       DsWarning, dsWarn, 
+       DsWarning, warnDs, failWithDs,
 
        -- Data types
        DsMatchContext(..),
-       EquationInfo(..), MatchResult(..), DsWrapper, idWrapper,
+       EquationInfo(..), MatchResult(..), DsWrapper, idDsWrapper,
        CanItFail(..), orFail
     ) where
 
 #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 CoreSyn
+import HsSyn
+import TcIface
+import RdrName
+import HscTypes
+import Bag
+import DataCon
+import TyCon
+import Id
+import Module
+import Var
 import Outputable
-import SrcLoc          ( noSrcSpan, SrcSpan )
-import Type             ( Type )
-import UniqSupply      ( UniqSupply, uniqsFromSupply )
-import Name            ( Name, nameOccName )
+import SrcLoc
+import Type
+import UniqSupply
+import Name
 import NameEnv
-import OccName          ( occNameFS )
-import DynFlags        ( DynFlags )
-import ErrUtils                ( WarnMsg, mkWarnMsg )
-import Bag             ( mapBag )
+import OccName
+import DynFlags
+import ErrUtils
+import Bag
+import OccName
 
-import DATA_IOREF      ( newIORef, readIORef )
+import Data.IORef
 
 infixr 9 `thenDs`
 \end{code}
@@ -74,12 +77,11 @@ data DsMatchContext
   deriving ()
 
 data EquationInfo
-  = EqnInfo { eqn_wrap :: DsWrapper,   -- Bindings
-             eqn_pats :: [Pat Id],     -- The patterns for an eqn
+  = EqnInfo { eqn_pats :: [Pat Id],            -- The patterns for an eqn
              eqn_rhs  :: MatchResult } -- What to do after match
 
 type DsWrapper = CoreExpr -> CoreExpr
-idWrapper e = e
+idDsWrapper e = e
 
 -- The semantics of (match vs (EqnInfo wrap pats rhs)) is the MatchResult
 --     \fail. wrap (case vs of { pats -> rhs fail })
@@ -131,14 +133,16 @@ type DsWarning = (SrcSpan, SDoc)
 
 data DsGblEnv = DsGblEnv {
        ds_mod     :: Module,                   -- For SCC profiling
-       ds_warns   :: IORef (Bag DsWarning),    -- Warning messages
+       ds_unqual  :: PrintUnqualified,
+       ds_msgs    :: IORef Messages,           -- 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
+       ds_loc     :: SrcSpan,          -- to put in pattern-matching error msgs
+        ds_locals  :: OccEnv Id         -- For locals in breakpoints
      }
 
 -- Inside [| |] brackets, the desugarer looks 
@@ -153,33 +157,61 @@ data DsMetaVal
    | 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  :: HscEnv
        -> Module -> GlobalRdrEnv -> TypeEnv
        -> DsM a
-       -> IO (a, Bag WarnMsg)
+       -> IO (Maybe a)
+-- Print errors and warnings, if any arise
 
 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
+  = do         { msg_var <- newIORef (emptyBag, emptyBag)
+        ; (ds_gbl_env, ds_lcl_env) <- mkDsEnvs mod rdr_env type_env msg_var
+
+       ; either_res <- initTcRnIf 'd' hsc_env ds_gbl_env ds_lcl_env $
+                       tryM thing_inside       -- Catch exceptions (= errors during desugaring)
+
+       -- Display any errors and warnings 
+       -- Note: if -Werror is used, we don't signal an error here.
+       ; let dflags = hsc_dflags hsc_env
+       ; msgs <- readIORef msg_var
+        ; printErrorsAndWarnings dflags msgs 
+
+       ; let final_res | errorsFound dflags msgs = Nothing
+                       | otherwise = case either_res of
+                                       Right res -> Just res
+                                       Left exn -> pprPanic "initDs" (text (show exn))
+               -- The (Left exn) case happens when the thing_inside throws
+               -- a UserError exception.  Then it should have put an error
+               -- message in msg_var, so we just discard the exception
+
+       ; return final_res }
+
+initDsTc :: DsM a -> TcM a
+initDsTc thing_inside
+  = do { this_mod <- getModule
+       ; tcg_env  <- getGblEnv
+       ; msg_var  <- getErrsVar
+       ; let type_env = tcg_type_env tcg_env
+             rdr_env  = tcg_rdr_env tcg_env
+        ; ds_envs <- ioToIOEnv$ mkDsEnvs this_mod rdr_env type_env msg_var
+       ; setEnvs ds_envs thing_inside }
+
+mkDsEnvs :: Module -> GlobalRdrEnv -> TypeEnv -> IORef Messages -> IO (DsGblEnv, DsLclEnv)
+mkDsEnvs mod rdr_env type_env msg_var
+  = do 
+       sites_var <- newIORef []
+       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_unqual = mkPrintUnqualified rdr_env,
+                                   ds_msgs = msg_var}
+               lcl_env = DsLclEnv { ds_meta = emptyNameEnv, 
+                                   ds_loc = noSrcSpan,
+                                    ds_locals = emptyOccEnv }
+
+       return (gbl_env, lcl_env)
+
 \end{code}
 
 %************************************************************************
@@ -232,6 +264,12 @@ the @SrcSpan@ being carried around.
 getDOptsDs :: DsM DynFlags
 getDOptsDs = getDOpts
 
+doptDs :: DynFlag -> TcRnIf gbl lcl Bool
+doptDs = doptM
+
+getGhcModeDs :: DsM GhcMode
+getGhcModeDs =  getDOptsDs >>= return . ghcMode
+
 getModuleDs :: DsM Module
 getModuleDs = do { env <- getGblEnv; return (ds_mod env) }
 
@@ -241,12 +279,22 @@ 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 
+warnDs :: SDoc -> DsM ()
+warnDs warn = do { env <- getGblEnv 
                 ; loc <- getSrcSpanDs
-                ; updMutVar (ds_warns env) (`snocBag` (loc,msg)) }
+                ; let msg = mkWarnMsg loc (ds_unqual env) 
+                                     (ptext SLIT("Warning:") <+> warn)
+                ; updMutVar (ds_msgs env) (\ (w,e) -> (w `snocBag` msg, e)) }
            where
-             msg = ptext SLIT("Warning:") <+> warn
+
+failWithDs :: SDoc -> DsM a
+failWithDs err 
+  = do { env <- getGblEnv 
+       ; loc <- getSrcSpanDs
+       ; let msg = mkErrMsg loc (ds_unqual env) err
+       ; updMutVar (ds_msgs env) (\ (w,e) -> (w, e `snocBag` msg))
+       ; failM }
+       where
 \end{code}
 
 \begin{code}
@@ -282,4 +330,14 @@ dsExtendMetaEnv menv thing_inside
   = updLclEnv (\env -> env { ds_meta = ds_meta env `plusNameEnv` menv }) thing_inside
 \end{code}
 
+\begin{code}
+getLocalBindsDs :: DsM [Id]
+getLocalBindsDs = do { env <- getLclEnv; return (occEnvElts$ ds_locals env) }
+
+bindLocalsDs :: [Id] -> DsM a -> DsM a
+bindLocalsDs new_ids enclosed_scope = 
+    updLclEnv (\env-> env {ds_locals = ds_locals env `extendOccEnvList` occnamed_ids})
+             enclosed_scope
+  where occnamed_ids = [ (nameOccName (idName id),id) | id <- new_ids ] 
+\end{code}