+ = getLclEnv `thenM` \ (TcLclEnv {tcl_tyvars = gtv_var}) ->
+ readMutVar gtv_var `thenM` \ gbl_tvs ->
+ zonkTcTyVarsAndFV (varSetElems gbl_tvs) `thenM` \ gbl_tvs' ->
+ writeMutVar gtv_var gbl_tvs' `thenM_`
+ returnM gbl_tvs'
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Rules}
+%* *
+%************************************************************************
+
+\begin{code}
+tcExtendRules :: [LRuleDecl Id] -> TcM a -> TcM a
+ -- Just pop the new rules into the EPS and envt resp
+ -- All the rules come from an interface file, not soruce
+ -- Nevertheless, some may be for this module, if we read
+ -- its interface instead of its source code
+tcExtendRules lcl_rules thing_inside
+ = do { env <- getGblEnv
+ ; let
+ env' = env { tcg_rules = lcl_rules ++ tcg_rules env }
+ ; setGblEnv env' thing_inside }
+\end{code}
+
+
+%************************************************************************
+%* *
+ 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 ThStage where
+ ppr Comp = text "Comp"
+ ppr (Brack l _ _) = text "Brack" <+> int l
+ ppr (Splice l) = text "Splice" <+> int l
+
+
+thLevel :: ThStage -> ThLevel
+thLevel Comp = topLevel
+thLevel (Splice l) = l
+thLevel (Brack l _ _) = l
+
+
+checkWellStaged :: SDoc -- What the stage check is for
+ -> 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!
+ = returnM ()
+
+ | bind_lvl == topLevel -- GHC restriction on top level splices
+ = failWithTc $
+ sep [ptext SLIT("GHC stage restriction:") <+> pp_thing,
+ nest 2 (ptext SLIT("is used in a top-level splice, and must be imported, not defined locally"))]
+
+ | otherwise -- Badly staged
+ = failWithTc $
+ ptext SLIT("Stage error:") <+> pp_thing <+>
+ hsep [ptext SLIT("is bound at stage") <+> ppr bind_lvl,
+ ptext SLIT("but used at stage") <+> ppr use_lvl]
+ where
+ use_lvl = thLevel use_stage
+
+
+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.
+-- Hence we give the former impLevel, but the latter topLevel
+-- E.g. this is bad:
+-- x = [| foo |]
+-- $( f x )
+-- By the time we are prcessing the $(f x), the binding for "x"
+-- will be in the global env, not the local one.
+topIdLvl id | isLocalId id = topLevel
+ | otherwise = impLevel
+
+-- Indicates the legal transitions on bracket( [| |] ).
+bracketOK :: ThStage -> Maybe ThLevel
+bracketOK (Brack _ _ _) = Nothing -- Bracket illegal inside a bracket
+bracketOK stage = Just (thLevel stage + 1)
+
+-- Indicates the legal transitions on splice($).
+spliceOK :: ThStage -> Maybe ThLevel
+spliceOK (Splice _) = Nothing -- Splice illegal inside splice
+spliceOK stage = Just (thLevel stage - 1)
+
+tcMetaTy :: Name -> TcM Type
+-- Given the name of a Template Haskell data type,
+-- return the type
+-- E.g. given the name "Expr" return the type "Expr"
+tcMetaTy tc_name
+ = tcLookupTyCon tc_name `thenM` \ t ->
+ returnM (mkGenTyConApp t [])
+ -- Use mkGenTyConApp because it might be a synonym