[project @ 2003-06-27 21:17:24 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcEnv.lhs
index edec045..5360887 100644 (file)
@@ -3,7 +3,7 @@ module TcEnv(
        TyThing(..), TyThingDetails(..), TcTyThing(..), TcId,
 
        -- Instance environment, and InstInfo type
-       tcGetInstEnv, tcSetInstEnv, 
+       tcGetInstEnv, 
        InstInfo(..), pprInstInfo, pprInstInfoDetails,
        simpleInstInfoTy, simpleInstInfoTyCon, 
        InstBindings(..),
@@ -21,11 +21,11 @@ module TcEnv(
        tcExtendTyVarEnv,    tcExtendTyVarEnv2, 
        tcExtendLocalValEnv, tcExtendLocalValEnv2, 
        tcLookup, tcLookupLocalIds, tcLookup_maybe, 
-       tcLookupId, tcLookupIdLvl, 
+       tcLookupId, 
        lclEnvElts, getInLocalScope, findGlobals, 
 
        -- Instance environment
-       tcExtendLocalInstEnv, tcExtendInstEnv, 
+       tcExtendLocalInstEnv, tcExtendInstEnv, tcExtendTempInstEnv, tcWithTempInstEnv,
 
        -- Rules
        tcExtendRules,
@@ -34,9 +34,12 @@ module TcEnv(
        tcGetGlobalTyVars,
 
        -- Template Haskell stuff
-       checkWellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel, 
+       checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel, 
        topIdLvl, 
 
+       -- Arrow stuff
+       checkProcLevel,
+
        -- New Ids
        newLocalName, newDFunName,
 
@@ -57,7 +60,7 @@ import TcType         ( Type, ThetaType, TcKind, TcTyVar, TcTyVarSet,
                        )
 import qualified Type  ( getTyVar_maybe )
 import Rules           ( extendRuleBase )
-import Id              ( idName, isLocalId, isDataConWrapId_maybe )
+import Id              ( idName, isLocalId )
 import Var             ( TyVar, Id, idType )
 import VarSet
 import VarEnv
@@ -76,7 +79,6 @@ import Rules          ( RuleBase )
 import BasicTypes      ( EP )
 import Module          ( Module )
 import InstEnv         ( InstEnv, extendInstEnv )
-import Maybes          ( seqMaybe )
 import SrcLoc          ( SrcLoc )
 import Outputable
 import Maybe           ( isJust )
@@ -86,26 +88,45 @@ import List         ( partition )
 
 %************************************************************************
 %*                                                                     *
+               Arrow notation proc levels
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+checkProcLevel :: TcId -> ProcLevel -> TcM ()
+checkProcLevel id id_lvl
+  = do { banned <- getBannedProcLevels
+       ; checkTc (not (id_lvl `elem` banned))
+                 (procLevelErr id id_lvl) }
+
+procLevelErr id id_lvl
+  = hang (ptext SLIT("Command-bound variable") <+> quotes (ppr id) <+> ptext SLIT("is not in scope here"))
+        4 (ptext SLIT("Reason: it is used in the left argument of (-<)"))
+\end{code}
+               
+
+%************************************************************************
+%*                                                                     *
                Meta level
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-instance Outputable Stage where
+instance Outputable ThStage where
    ppr Comp         = text "Comp"
    ppr (Brack l _ _) = text "Brack" <+> int l
    ppr (Splice l)    = text "Splice" <+> int l
 
 
-metaLevel :: Stage -> Level
-metaLevel Comp         = topLevel
-metaLevel (Splice l)    = l
-metaLevel (Brack l _ _) = l
+thLevel :: ThStage -> ThLevel
+thLevel Comp         = topLevel
+thLevel (Splice l)    = l
+thLevel (Brack l _ _) = l
 
 
 checkWellStaged :: SDoc                -- What the stage check is for
-               -> Level        -- Binding level
-               -> Stage        -- Use stage
+               -> ThLevel      -- Binding level
+               -> ThStage      -- Use stage
                -> TcM ()       -- Fail if badly staged, adding an error
 checkWellStaged pp_thing bind_lvl use_stage
   | bind_lvl <= use_lvl        -- OK!
@@ -122,10 +143,10 @@ checkWellStaged pp_thing bind_lvl use_stage
        hsep   [ptext SLIT("is bound at stage") <+> ppr bind_lvl,
                ptext SLIT("but used at stage") <+> ppr use_lvl]
   where
-    use_lvl = metaLevel use_stage
+    use_lvl = thLevel use_stage
 
 
-topIdLvl :: Id -> Level
+topIdLvl :: Id -> ThLevel
 -- Globals may either be imported, or may be from an earlier "chunk" 
 -- (separated by declaration splices) of this module.  The former
 -- *can* be used inside a top-level splice, but the latter cannot.
@@ -139,14 +160,14 @@ topIdLvl id | isLocalId id = topLevel
            | otherwise    = impLevel
 
 -- Indicates the legal transitions on bracket( [| |] ).
-bracketOK :: Stage -> Maybe Level
+bracketOK :: ThStage -> Maybe ThLevel
 bracketOK (Brack _ _ _) = Nothing      -- Bracket illegal inside a bracket
-bracketOK stage         = (Just (metaLevel stage + 1))
+bracketOK stage         = (Just (thLevel stage + 1))
 
 -- Indicates the legal transitions on splice($).
-spliceOK :: Stage -> Maybe Level
+spliceOK :: ThStage -> Maybe ThLevel
 spliceOK (Splice _) = Nothing  -- Splice illegal inside splice
-spliceOK stage      = Just (metaLevel stage - 1)
+spliceOK stage      = Just (thLevel stage - 1)
 
 tcMetaTy :: Name -> TcM Type
 -- Given the name of a Template Haskell data type, 
@@ -282,18 +303,19 @@ tcLookupGlobal name
        other      -> notFound "tcLookupGlobal" name
 
 tcLookupGlobalId :: Name -> TcM Id
+-- Never used for Haskell-source DataCons, hence no ADataCon case
 tcLookupGlobalId name
   = tcLookupGlobal_maybe name  `thenM` \ maybe_thing ->
     case maybe_thing of
        Just (AnId id) -> returnM id
-       other          -> notFound "tcLookupGlobal" name
+       other          -> notFound "tcLookupGlobal (id)" name
 
 tcLookupDataCon :: Name -> TcM DataCon
 tcLookupDataCon con_name
-  = tcLookupGlobalId con_name  `thenM` \ con_id ->
-    case isDataConWrapId_maybe con_id of
-       Just data_con -> returnM data_con
-       Nothing       -> failWithTc (badCon con_id)
+  = tcLookupGlobal_maybe con_name      `thenM` \ maybe_thing ->
+    case maybe_thing of
+       Just (ADataCon data_con) -> returnM data_con
+       other                    -> notFound "tcLookupDataCon" con_name
 
 tcLookupClass :: Name -> TcM Class
 tcLookupClass name
@@ -350,32 +372,25 @@ tcLookup name
 
 tcLookupId :: Name -> TcM Id
 -- Used when we aren't interested in the binding level
+-- Never a DataCon. (Why does that matter? see TcExpr.tcId)
 tcLookupId name
   = tcLookup name      `thenM` \ thing -> 
     case thing of
-       ATcId tc_id lvl   -> returnM tc_id
+       ATcId tc_id _ _   -> returnM tc_id
        AGlobal (AnId id) -> returnM id
        other             -> pprPanic "tcLookupId" (ppr name)
 
-tcLookupIdLvl :: Name -> TcM (Id, Level)
-tcLookupIdLvl name
-  = tcLookup name      `thenM` \ thing -> 
-    case thing of
-       ATcId tc_id lvl   -> returnM (tc_id, lvl)
-       AGlobal (AnId id) -> returnM (id, topIdLvl id)
-       other             -> pprPanic "tcLookupIdLvl" (ppr name)
-
 tcLookupLocalIds :: [Name] -> TcM [TcId]
 -- We expect the variables to all be bound, and all at
 -- the same level as the lookup.  Only used in one place...
 tcLookupLocalIds ns
   = getLclEnv          `thenM` \ env ->
-    returnM (map (lookup (tcl_env env) (metaLevel (tcl_level env))) ns)
+    returnM (map (lookup (tcl_env env) (thLevel (tcl_th_ctxt env))) ns)
   where
     lookup lenv lvl name 
        = case lookupNameEnv lenv name of
-               Just (ATcId id lvl1) -> ASSERT( lvl == lvl1 ) id
-               other                -> pprPanic "tcLookupLocalIds" (ppr name)
+               Just (ATcId id lvl1 _) -> ASSERT( lvl == lvl1 ) id
+               other                  -> pprPanic "tcLookupLocalIds" (ppr name)
 
 lclEnvElts :: TcLclEnv -> [TcTyThing]
 lclEnvElts env = nameEnvElts (tcl_env env)
@@ -431,8 +446,9 @@ tcExtendLocalValEnv ids thing_inside
   = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
-       lvl                 = metaLevel (tcl_level env)
-       extra_env           = [(idName id, ATcId id lvl) | id <- ids]
+       th_lvl              = thLevel (tcl_th_ctxt env)
+       proc_lvl            = proc_level (tcl_arrow_ctxt env)
+       extra_env           = [(idName id, ATcId id th_lvl proc_lvl) | id <- ids]
        le'                 = extendNameEnvList (tcl_env env) extra_env
     in
     tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
@@ -443,8 +459,9 @@ tcExtendLocalValEnv2 names_w_ids thing_inside
   = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | (name,id) <- names_w_ids]
-       lvl                 = metaLevel (tcl_level env)
-       extra_env           = [(name, ATcId id lvl) | (name,id) <- names_w_ids]
+       th_lvl              = thLevel    (tcl_th_ctxt   env)
+       proc_lvl            = proc_level (tcl_arrow_ctxt env)
+       extra_env           = [(name, ATcId id th_lvl proc_lvl) | (name,id) <- names_w_ids]
        le'                 = extendNameEnvList (tcl_env env) extra_env
     in
     tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
@@ -477,7 +494,7 @@ findGlobals tvs tidy_env
     ignore_it ty = not (tvs `intersectsVarSet` tyVarsOfType ty)
 
 -----------------------
-find_thing ignore_it tidy_env (ATcId id _)
+find_thing ignore_it tidy_env (ATcId id _ _)
   = zonkTcType  (idType id)    `thenM` \ id_ty ->
     if ignore_it id_ty then
        returnM (tidy_env, Nothing)
@@ -549,23 +566,7 @@ from this module
 
 \begin{code}
 tcGetInstEnv :: TcM InstEnv
-tcGetInstEnv = getGblEnv       `thenM` \ env -> 
-              readMutVar (tcg_inst_env env)
-
-tcSetInstEnv :: InstEnv -> TcM a -> TcM a
--- Horribly imperative; 
--- but used only when temporarily enhancing the instance
--- envt during 'deriving' context inference
-tcSetInstEnv ie thing_inside
-  = getGblEnv  `thenM` \ env ->
-    let 
-       ie_var = tcg_inst_env env
-    in
-    readMutVar  ie_var         `thenM` \ old_ie ->
-    writeMutVar ie_var ie      `thenM_`
-    thing_inside               `thenM` \ result ->
-    writeMutVar ie_var old_ie  `thenM_`    
-    returnM result
+tcGetInstEnv = do { env <- getGblEnv; readMutVar (tcg_inst_env env) }
 
 tcExtendInstEnv :: [DFunId] -> TcM a -> TcM a
        -- Add instances from local or imported
@@ -612,10 +613,38 @@ tcExtendLocalInstEnv infos thing_inside
       ; writeMutVar ie_var inst_env'
       ; setGblEnv env' thing_inside }
 
+tcExtendTempInstEnv :: [DFunId] -> TcM a -> TcM a
+  -- Extend the instance envt, but with *no* permanent 
+  -- effect on mutable variables; also ignore errors
+  -- Used during 'deriving' stuff
+tcExtendTempInstEnv dfuns thing_inside
+ = do { dflags <- getDOpts
+      ; env <- getGblEnv
+      ; let ie_var = tcg_inst_env env
+      ; inst_env <- readMutVar ie_var
+      ; let (inst_env', errs) = extendInstEnv dflags inst_env dfuns
+       -- Ignore the errors about duplicate instances.
+       -- We don't want repeated error messages
+       -- They'll appear later, when we do the top-level extendInstEnvs
+      ; writeMutVar ie_var inst_env'
+      ; result <- thing_inside 
+      ; writeMutVar ie_var inst_env    -- Restore!
+      ; return result }
+
+tcWithTempInstEnv :: TcM a -> TcM a
+-- Run thing_inside, discarding any effects on the instance environment
+tcWithTempInstEnv thing_inside
+   = do { env <- getGblEnv
+       ; let ie_var = tcg_inst_env env
+       ; old_ie <- readMutVar  ie_var
+       ; result <- thing_inside
+       ; writeMutVar ie_var old_ie     -- Restore
+       ; return result }
+
 traceDFuns dfuns
   = traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
   where
-    pp dfun   = ppr dfun <+> dcolon <+> ppr (idType dfun)
+    pp dfun = ppr dfun <+> dcolon <+> ppr (idType dfun)
 \end{code}