Template Haskell: allow type splices
[ghc-hetmet.git] / compiler / typecheck / TcSplice.lhs
index 9ec400d..7b92b81 100644 (file)
@@ -6,14 +6,16 @@
 TcSplice: Template Haskell splices
 
 \begin{code}
-{-# OPTIONS -w #-}
+{-# OPTIONS -fno-warn-unused-imports -fno-warn-unused-binds #-}
 -- The above warning supression flag is a temporary kludge.
 -- While working on this module you are encouraged to remove it and fix
 -- any warnings in the module. See
 --     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
 -- for details
 
-module TcSplice( tcSpliceExpr, tcSpliceDecls, tcBracket ) where
+module TcSplice( kcSpliceType, tcSpliceExpr, tcSpliceDecls, tcBracket,
+                 lookupThName_maybe,
+                 runQuasiQuoteExpr, runQuasiQuotePat, runAnnotation ) where
 
 #include "HsVersions.h"
 
@@ -40,13 +42,15 @@ import TcIface
 import TypeRep
 import Name
 import NameEnv
+import PrelNames
 import HscTypes
 import OccName
 import Var
 import Module
+import Annotations
 import TcRnMonad
-import IfaceEnv
 import Class
+import Inst
 import TyCon
 import DataCon
 import Id
@@ -55,24 +59,28 @@ import TysWiredIn
 import DsMeta
 import DsExpr
 import DsMonad hiding (Splice)
+import Serialized
 import ErrUtils
 import SrcLoc
 import Outputable
 import Unique
-import DynFlags
-import PackageConfig
 import Maybe
 import BasicTypes
 import Panic
 import FastString
+import Exception
 
 import qualified Language.Haskell.TH as TH
 -- THSyntax gives access to internal functions and data types
 import qualified Language.Haskell.TH.Syntax as TH
 
+#ifdef GHCI
+-- Because GHC.Desugar might not be in the base library of the bootstrapping compiler
+import GHC.Desugar      ( AnnotationWrapper(..) )
+#endif
+
 import GHC.Exts                ( unsafeCoerce#, Int#, Int(..) )
-import Control.Monad   ( liftM )
-import qualified Control.Exception  as Exception( userErrors )
+import System.IO.Error
 \end{code}
 
 Note [Template Haskell levels]
@@ -160,14 +168,29 @@ The predicate we use is TcEnv.thTopLevelId.
 %************************************************************************
 
 \begin{code}
+tcBracket     :: HsBracket Name -> BoxyRhoType -> TcM (LHsExpr TcId)
 tcSpliceDecls :: LHsExpr Name -> TcM [LHsDecl RdrName]
 tcSpliceExpr  :: HsSplice Name -> BoxyRhoType -> TcM (HsExpr TcId)
 kcSpliceType  :: HsSplice Name -> TcM (HsType Name, TcKind)
        -- None of these functions add constraints to the LIE
 
+lookupThName_maybe :: TH.Name -> TcM (Maybe Name)
+
+runQuasiQuoteExpr :: HsQuasiQuote Name -> TcM (LHsExpr RdrName)
+runQuasiQuotePat  :: HsQuasiQuote Name -> TcM (LPat RdrName)
+runAnnotation     :: CoreAnnTarget -> LHsExpr Name -> TcM Annotation
+
 #ifndef GHCI
-tcSpliceExpr n e ty = pprPanic "Cant do tcSpliceExpr without GHCi" (ppr e)
-tcSpliceDecls e     = pprPanic "Cant do tcSpliceDecls without GHCi" (ppr e)
+tcBracket     x _ = pprPanic "Cant do tcBracket without GHCi"     (ppr x)
+tcSpliceExpr  e   = pprPanic "Cant do tcSpliceExpr without GHCi"  (ppr e)
+tcSpliceDecls x   = pprPanic "Cant do tcSpliceDecls without GHCi" (ppr x)
+kcSpliceType  x   = pprPanic "Cant do kcSpliceType without GHCi"  (ppr x)
+
+lookupThName_maybe n = pprPanic "Cant do lookupThName_maybe without GHCi" (ppr n)
+
+runQuasiQuoteExpr q = pprPanic "Cant do runQuasiQuoteExpr without GHCi" (ppr q)
+runQuasiQuotePat  q = pprPanic "Cant do runQuasiQuotePat without GHCi" (ppr q)
+runAnnotation   _ q = pprPanic "Cant do runAnnotation without GHCi" (ppr q)
 #else
 \end{code}
 
@@ -190,32 +213,31 @@ Desugared:        f = do { s7 <- g Int 3
                       ; return (ConE "Data.Maybe.Just" s7) }
 
 \begin{code}
-tcBracket :: HsBracket Name -> BoxyRhoType -> TcM (LHsExpr TcId)
-tcBracket brack res_ty
-  = getStage                           `thenM` \ level ->
-    case bracketOK level of {
-       Nothing         -> failWithTc (illegalBracket level) ;
-       Just next_level ->
+tcBracket brack res_ty 
+  = addErrCtxt (hang (ptext (sLit "In the Template Haskell quotation"))
+                   2 (ppr brack)) $
+    do { level <- getStage
+       ; case bracketOK level of {
+          Nothing         -> failWithTc (illegalBracket level) ;
+          Just next_level -> do {
 
        -- Typecheck expr to make sure it is valid,
        -- but throw away the results.  We'll type check
        -- it again when we actually use it.
-    recordThUse                                `thenM_`
-    newMutVar []                       `thenM` \ pending_splices ->
-    getLIEVar                          `thenM` \ lie_var ->
+          recordThUse
+       ; pending_splices <- newMutVar []
+       ; lie_var <- getLIEVar
 
-    setStage (Brack next_level pending_splices lie_var) (
-       getLIE (tc_bracket next_level brack)
-    )                                  `thenM` \ (meta_ty, lie) ->
-    tcSimplifyBracket lie              `thenM_`  
+       ; (meta_ty, lie) <- setStage (Brack next_level pending_splices lie_var)
+                                    (getLIE (tc_bracket next_level brack))
+       ; tcSimplifyBracket lie
 
        -- Make the expected type have the right shape
-    boxyUnify meta_ty res_ty           `thenM_`
+       ; boxyUnify meta_ty res_ty
 
        -- Return the original expression, not the type-decorated one
-    readMutVar pending_splices         `thenM` \ pendings ->
-    returnM (noLoc (HsBracketOut brack pendings))
-    }
+       ; pendings <- readMutVar pending_splices
+       ; return (noLoc (HsBracketOut brack pendings)) }}}
 
 tc_bracket :: ThLevel -> HsBracket Name -> TcM TcType
 tc_bracket use_lvl (VarBr name)        -- Note [Quoting names]
@@ -228,23 +250,23 @@ tc_bracket use_lvl (VarBr name)   -- Note [Quoting names]
                | otherwise
                -> do { checkTc (use_lvl == bind_lvl)
                                (quotedNameStageErr name) }
-           other -> pprPanic "th_bracket" (ppr name)
+           _ -> pprPanic "th_bracket" (ppr name)
 
        ; tcMetaTy nameTyConName        -- Result type is Var (not Q-monadic)
        }
 
-tc_bracket use_lvl (ExpBr expr) 
+tc_bracket _ (ExpBr expr) 
   = do { any_ty <- newFlexiTyVarTy liftedTypeKind
-       ; tcMonoExpr expr any_ty
+       ; tcMonoExprNC expr any_ty  -- NC for no context; tcBracket does that
        ; tcMetaTy expQTyConName }
        -- Result type is Expr (= Q Exp)
 
-tc_bracket use_lvl (TypBr typ) 
-  = do { tcHsSigType ExprSigCtxt typ
+tc_bracket _ (TypBr typ) 
+  = do { tcHsSigTypeNC ThBrackCtxt typ
        ; tcMetaTy typeQTyConName }
        -- Result type is Type (= Q Typ)
 
-tc_bracket use_lvl (DecBr decls)
+tc_bracket _ (DecBr decls)
   = do {  tcTopSrcDecls emptyModDetails decls
        -- Typecheck the declarations, dicarding the result
        -- We'll get all that stuff later, when we splice it in
@@ -255,12 +277,13 @@ tc_bracket use_lvl (DecBr decls)
        -- Result type is Q [Dec]
     }
 
-tc_bracket use_lvl (PatBr _)
-  = failWithTc (ptext SLIT("Tempate Haskell pattern brackets are not supported yet"))
+tc_bracket _ (PatBr _)
+  = failWithTc (ptext (sLit "Tempate Haskell pattern brackets are not supported yet"))
 
+quotedNameStageErr :: Name -> SDoc
 quotedNameStageErr v 
-  = sep [ ptext SLIT("Stage error: the non-top-level quoted name") <+> ppr (VarBr v)
-       , ptext SLIT("must be used at the same stage at which is is bound")]
+  = sep [ ptext (sLit "Stage error: the non-top-level quoted name") <+> ppr (VarBr v)
+       , ptext (sLit "must be used at the same stage at which is is bound")]
 \end{code}
 
 
@@ -272,16 +295,16 @@ quotedNameStageErr v
 
 \begin{code}
 tcSpliceExpr (HsSplice name expr) res_ty
-  = setSrcSpan (getLoc expr)   $
-    getStage           `thenM` \ level ->
+  = setSrcSpan (getLoc expr)   $ do
+    level <- getStage
     case spliceOK level of {
        Nothing         -> failWithTc (illegalSplice level) ;
        Just next_level -> 
 
-    case level of {
-       Comp                   -> do { e <- tcTopSplice expr res_ty
-                                    ; returnM (unLoc e) } ;
-       Brack _ ps_var lie_var ->  
+     case level of {
+       Comp _                 -> do { e <- tcTopSplice expr res_ty
+                                    ; return (unLoc e) } ;
+       Brack _ ps_var lie_var -> do
 
        -- A splice inside brackets
        -- NB: ignore res_ty, apart from zapping it to a mono-type
@@ -289,19 +312,21 @@ tcSpliceExpr (HsSplice name expr) res_ty
        -- Here (h 4) :: Q Exp
        -- but $(h 4) :: forall a.a     i.e. anything!
 
-    unBox res_ty                               `thenM_`
-    tcMetaTy expQTyConName                     `thenM` \ meta_exp_ty ->
-    setStage (Splice next_level) (
-       setLIEVar lie_var          $
-       tcMonoExpr expr meta_exp_ty
-    )                                          `thenM` \ expr' ->
+      unBox res_ty
+      meta_exp_ty <- tcMetaTy expQTyConName
+      expr' <- setStage (Splice next_level) (
+                 setLIEVar lie_var    $
+                 tcMonoExpr expr meta_exp_ty
+               )
 
        -- Write the pending splice into the bucket
-    readMutVar ps_var                          `thenM` \ ps ->
-    writeMutVar ps_var ((name,expr') : ps)     `thenM_`
+      ps <- readMutVar ps_var
+      writeMutVar ps_var ((name,expr') : ps)
 
-    returnM (panic "tcSpliceExpr")     -- The returned expression is ignored
-    }} 
+      return (panic "tcSpliceExpr")    -- The returned expression is ignored
+
+     ; Splice {} -> panic "tcSpliceExpr Splice"
+     }} 
 
 -- tcTopSplice used to have this:
 -- Note that we do not decrement the level (to -1) before 
@@ -311,24 +336,24 @@ tcSpliceExpr (HsSplice name expr) res_ty
 -- inner escape before dealing with the outer one
 
 tcTopSplice :: LHsExpr Name -> BoxyRhoType -> TcM (LHsExpr Id)
-tcTopSplice expr res_ty
-  = tcMetaTy expQTyConName             `thenM` \ meta_exp_ty ->
+tcTopSplice expr res_ty = do
+    meta_exp_ty <- tcMetaTy expQTyConName
 
-       -- Typecheck the expression
-    tcTopSpliceExpr expr meta_exp_ty   `thenM` \ zonked_q_expr ->
+        -- Typecheck the expression
+    zonked_q_expr <- tcTopSpliceExpr expr meta_exp_ty
 
-       -- Run the expression
-    traceTc (text "About to run" <+> ppr zonked_q_expr)        `thenM_`
-    runMetaE convertToHsExpr zonked_q_expr     `thenM` \ expr2 ->
-  
-    traceTc (text "Got result" <+> ppr expr2)  `thenM_`
+        -- Run the expression
+    traceTc (text "About to run" <+> ppr zonked_q_expr)
+    expr2 <- runMetaE convertToHsExpr zonked_q_expr
+
+    traceTc (text "Got result" <+> ppr expr2)
 
     showSplice "expression" 
-              zonked_q_expr (ppr expr2)        `thenM_`
+               zonked_q_expr (ppr expr2)
 
-       -- Rename it, but bale out if there are errors
-       -- otherwise the type checker just gives more spurious errors
-    checkNoErrs (rnLExpr expr2)                        `thenM` \ (exp3, fvs) ->
+        -- Rename it, but bale out if there are errors
+        -- otherwise the type checker just gives more spurious errors
+    (exp3, _fvs) <- checkNoErrs (rnLExpr expr2)
 
     tcMonoExpr exp3 res_ty
 
@@ -336,23 +361,148 @@ tcTopSplice expr res_ty
 tcTopSpliceExpr :: LHsExpr Name -> TcType -> TcM (LHsExpr Id)
 -- Type check an expression that is the body of a top-level splice
 --   (the caller will compile and run it)
-tcTopSpliceExpr expr meta_ty
-  = checkNoErrs $      -- checkNoErrs: must not try to run the thing
-                       --              if the type checker fails!
+tcTopSpliceExpr expr meta_ty 
+  = checkNoErrs $  -- checkNoErrs: must not try to run the thing
+                   -- if the type checker fails!
+    do { (expr', const_binds) <- tcSimplifyStagedExpr topSpliceStage $
+                                 (recordThUse >> tcMonoExpr expr meta_ty)
+          -- Zonk it and tie the knot of dictionary bindings
+       ; zonkTopLExpr (mkHsDictLet const_binds expr') }
+\end{code}
 
-    setStage topSpliceStage $ do
 
-       
-    do { recordThUse   -- Record that TH is used (for pkg depdendency)
+%************************************************************************
+%*                                                                     *
+       Annotations
+%*                                                                     *
+%************************************************************************
 
-       -- Typecheck the expression
-       ; (expr', lie) <- getLIE (tcMonoExpr expr meta_ty)
-       
-       -- Solve the constraints
-       ; const_binds <- tcSimplifyTop lie
-       
-       -- And zonk it
-       ; zonkTopLExpr (mkHsDictLet const_binds expr') }
+\begin{code}
+runAnnotation target expr = do
+    expr_ty <- newFlexiTyVarTy liftedTypeKind
+    
+    -- Find the classes we want instances for in order to call toAnnotationWrapper
+    data_class <- tcLookupClass dataClassName
+    
+    -- Check the instances we require live in another module (we want to execute it..)
+    -- and check identifiers live in other modules using TH stage checks. tcSimplifyStagedExpr
+    -- also resolves the LIE constraints to detect e.g. instance ambiguity
+    ((wrapper, expr'), const_binds) <- tcSimplifyStagedExpr topAnnStage $ do
+                expr' <- tcPolyExprNC expr expr_ty
+                -- By instantiating the call >here< it gets registered in the 
+               -- LIE consulted by tcSimplifyStagedExpr
+                -- and hence ensures the appropriate dictionary is bound by const_binds
+                wrapper <- instCall AnnOrigin [expr_ty] [mkClassPred data_class [expr_ty]]
+                return (wrapper, expr')
+
+    -- We manually wrap the typechecked expression in a call to toAnnotationWrapper
+    loc <- getSrcSpanM
+    to_annotation_wrapper_id <- tcLookupId toAnnotationWrapperName
+    let specialised_to_annotation_wrapper_expr = L loc (HsWrap wrapper (HsVar to_annotation_wrapper_id))
+        wrapped_expr' = mkHsDictLet const_binds $
+                        L loc (HsApp specialised_to_annotation_wrapper_expr expr')
+
+    -- If we have type checking problems then potentially zonking 
+    -- (and certainly compilation) may fail. Give up NOW!
+    failIfErrsM
+
+    -- Zonk the type variables out of that raw expression. Note that
+    -- in particular we don't call recordThUse, since we don't
+    -- necessarily use any code or definitions from that package.
+    zonked_wrapped_expr' <- zonkTopLExpr wrapped_expr'
+
+    -- Run the appropriately wrapped expression to get the value of
+    -- the annotation and its dictionaries. The return value is of
+    -- type AnnotationWrapper by construction, so this conversion is
+    -- safe
+    flip runMetaAW zonked_wrapped_expr' $ \annotation_wrapper ->
+        case annotation_wrapper of
+            AnnotationWrapper value | let serialized = toSerialized serializeWithData value ->
+                -- Got the value and dictionaries: build the serialized value and 
+               -- call it a day. We ensure that we seq the entire serialized value 
+               -- in order that any errors in the user-written code for the
+                -- annotation are exposed at this point.  This is also why we are 
+               -- doing all this stuff inside the context of runMeta: it has the 
+               -- facilities to deal with user error in a meta-level expression
+                seqSerialized serialized `seq` Annotation { 
+                    ann_target = target,
+                    ann_value = serialized
+                }
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+       Quasi-quoting
+%*                                                                     *
+%************************************************************************
+
+Note [Quasi-quote overview]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The GHC "quasi-quote" extension is described by Geoff Mainland's paper
+"Why it's nice to be quoted: quasiquoting for Haskell" (Haskell
+Workshop 2007).
+
+Briefly, one writes
+       [:p| stuff |]
+and the arbitrary string "stuff" gets parsed by the parser 'p', whose
+type should be Language.Haskell.TH.Quote.QuasiQuoter.  'p' must be
+defined in another module, because we are going to run it here.  It's
+a bit like a TH splice:
+       $(p "stuff")
+
+However, you can do this in patterns as well as terms.  Becuase of this,
+the splice is run by the *renamer* rather than the type checker.
+
+\begin{code}
+runQuasiQuote :: Outputable hs_syn
+              => HsQuasiQuote Name     -- Contains term of type QuasiQuoter, and the String
+              -> Name                  -- Of type QuasiQuoter -> String -> Q th_syn
+              -> String                        -- Documentation string only
+              -> Name                  -- Name of th_syn type  
+              -> (SrcSpan -> th_syn -> Either Message hs_syn)
+              -> TcM hs_syn
+runQuasiQuote (HsQuasiQuote _name quoter q_span quote) quote_selector desc meta_ty convert
+  = do { -- Check that the quoter is not locally defined, otherwise the TH
+          -- machinery will not be able to run the quasiquote.
+        ; this_mod <- getModule
+        ; let is_local = case nameModule_maybe quoter of
+                           Just mod | mod == this_mod -> True
+                                    | otherwise       -> False
+                           Nothing -> True
+       ; traceTc (text "runQQ" <+> ppr quoter <+> ppr is_local)
+        ; checkTc (not is_local) (quoteStageError quoter)
+
+         -- Build the expression 
+       ; let quoterExpr = L q_span $! HsVar $! quoter
+       ; let quoteExpr = L q_span $! HsLit $! HsString quote
+       ; let expr = L q_span $
+                    HsApp (L q_span $
+                           HsApp (L q_span (HsVar quote_selector)) quoterExpr) quoteExpr
+       ; recordThUse
+       ; meta_exp_ty <- tcMetaTy meta_ty
+
+       -- Typecheck the expression
+       ; zonked_q_expr <- tcTopSpliceExpr expr meta_exp_ty
+
+       -- Run the expression
+       ; traceTc (text "About to run" <+> ppr zonked_q_expr)
+       ; result <- runMetaQ convert zonked_q_expr
+       ; traceTc (text "Got result" <+> ppr result)
+       ; showSplice desc zonked_q_expr (ppr result)
+       ; return result
+       }
+
+runQuasiQuoteExpr quasiquote
+    = runQuasiQuote quasiquote quoteExpName "expression" expQTyConName convertToHsExpr
+
+runQuasiQuotePat quasiquote
+    = runQuasiQuote quasiquote quotePatName "pattern" patQTyConName convertToPat
+
+quoteStageError :: Name -> SDoc
+quoteStageError quoter
+  = sep [ptext (sLit "GHC stage restriction:") <+> ppr quoter,
+         nest 2 (ptext (sLit "is used in a quasiquote, and must be imported, not defined locally"))]
 \end{code}
 
 
@@ -373,7 +523,7 @@ kcSpliceType (HsSplice name hs_expr)
                Just next_level -> do 
 
        { case level of {
-               Comp                   -> do { (t,k) <- kcTopSpliceType hs_expr 
+               Comp _                 -> do { (t,k) <- kcTopSpliceType hs_expr 
                                             ; return (unLoc t, k) } ;
                Brack _ ps_var lie_var -> do
 
@@ -391,8 +541,10 @@ kcSpliceType (HsSplice name hs_expr)
        -- Here (h 4) :: Q Type
        -- but $(h 4) :: forall a.a     i.e. any kind
        ; kind <- newKindVar
-       ; returnM (panic "kcSpliceType", kind)  -- The returned type is ignored
-    }}}}}
+       ; return (panic "kcSpliceType", kind)   -- The returned type is ignored
+    }
+        ; Splice {} -> panic "kcSpliceType Splice"
+    }}}}
 
 kcTopSpliceType :: LHsExpr Name -> TcM (LHsType Name, TcKind)
 kcTopSpliceType expr
@@ -411,10 +563,10 @@ kcTopSpliceType expr
 
        -- Rename it, but bale out if there are errors
        -- otherwise the type checker just gives more spurious errors
-       ; let doc = ptext SLIT("In the spliced type") <+> ppr hs_ty2
+       ; let doc = ptext (sLit "In the spliced type") <+> ppr hs_ty2
        ; hs_ty3 <- checkNoErrs (rnLHsType doc hs_ty2)
 
-       ; kcHsType hs_ty3 }
+       ; kcLHsType hs_ty3 }
 \end{code}
 
 %************************************************************************
@@ -441,13 +593,7 @@ tcSpliceDecls expr
        ; showSplice "declarations"
                     zonked_q_expr 
                     (ppr (getLoc expr) $$ (vcat (map ppr decls)))
-       ; returnM decls }
-
-  where handleErrors :: [Either a Message] -> TcM [a]
-        handleErrors [] = return []
-        handleErrors (Left x:xs) = liftM (x:) (handleErrors xs)
-        handleErrors (Right m:xs) = do addErrTc m
-                                       handleErrors xs
+       ; return decls }
 \end{code}
 
 
@@ -458,31 +604,55 @@ tcSpliceDecls expr
 %************************************************************************
 
 \begin{code}
+runMetaAW :: (AnnotationWrapper -> output)
+          -> LHsExpr Id         -- Of type AnnotationWrapper
+          -> TcM output
+runMetaAW k = runMeta False (\_ -> return . Right . k)
+    -- We turn off showing the code in meta-level exceptions because doing so exposes
+    -- the toAnnotationWrapper function that we slap around the users code
+
+runQThen :: (SrcSpan -> input -> Either Message output)
+         -> SrcSpan
+         -> TH.Q input
+         -> TcM (Either Message output)
+runQThen f expr_span what = TH.runQ what >>= (return . f expr_span)
+
+runMetaQ :: (SrcSpan -> input -> Either Message output)
+        -> LHsExpr Id
+        -> TcM output
+runMetaQ = runMeta True . runQThen
+
 runMetaE :: (SrcSpan -> TH.Exp -> Either Message (LHsExpr RdrName))
         -> LHsExpr Id          -- Of type (Q Exp)
         -> TcM (LHsExpr RdrName)
-runMetaE  = runMeta
+runMetaE = runMetaQ
+
+runMetaP :: (SrcSpan -> TH.Pat -> Either Message (Pat RdrName))
+         -> LHsExpr Id          -- Of type (Q Pat)
+         -> TcM (Pat RdrName)
+runMetaP = runMetaQ
 
 runMetaT :: (SrcSpan -> TH.Type -> Either Message (LHsType RdrName))
         -> LHsExpr Id          -- Of type (Q Type)
         -> TcM (LHsType RdrName)       
-runMetaT = runMeta
+runMetaT = runMetaQ
 
 runMetaD :: (SrcSpan -> [TH.Dec] -> Either Message [LHsDecl RdrName])
         -> LHsExpr Id          -- Of type Q [Dec]
         -> TcM [LHsDecl RdrName]
-runMetaD = runMeta 
+runMetaD = runMetaQ
 
-runMeta :: (SrcSpan -> th_syn -> Either Message hs_syn)
+runMeta :: Bool                 -- Whether code should be printed in the exception message
+        -> (SrcSpan -> input -> TcM (Either Message output))
        -> LHsExpr Id           -- Of type X
-       -> TcM hs_syn           -- Of type t
-runMeta convert expr
+       -> TcM output           -- Of type t
+runMeta show_code run_and_convert expr
   = do {       -- Desugar
          ds_expr <- initDsTc (dsLExpr expr)
        -- Compile and link it; might fail if linking fails
        ; hsc_env <- getTopEnv
        ; src_span <- getSrcSpanM
-       ; either_hval <- tryM $ ioToTcRn $
+       ; either_hval <- tryM $ liftIO $
                         HscMain.compileExpr hsc_env src_span ds_expr
        ; case either_hval of {
            Left exn   -> failWithTc (mk_msg "compile and link" exn) ;
@@ -499,23 +669,27 @@ runMeta convert expr
                -- encounter them inside the try
                --
                -- See Note [Exceptions in TH] 
-         either_tval <- tryAllM $ do
-               { th_syn <- TH.runQ (unsafeCoerce# hval)
-               ; case convert (getLoc expr) th_syn of
+         let expr_span = getLoc expr
+       ; either_tval <- tryAllM $
+                        setSrcSpan expr_span $ -- Set the span so that qLocation can
+                                               -- see where this splice is
+            do { mb_result <- run_and_convert expr_span (unsafeCoerce# hval)
+               ; case mb_result of
                    Left err     -> failWithTc err
-                   Right hs_syn -> return hs_syn }
+                   Right result -> return $! result }
 
        ; case either_tval of
            Right v -> return v
-           Left exn | Just s <- Exception.userErrors exn
-                    , s == "IOEnv failure" 
-                    -> failM   -- Error already in Tc monad
-                    | otherwise -> failWithTc (mk_msg "run" exn)       -- Exception
+           Left se ->
+                    case fromException se of
+                    Just IOEnvFailure ->
+                        failM -- Error already in Tc monad
+                    _ -> failWithTc (mk_msg "run" se)  -- Exception
         }}}
   where
     mk_msg s exn = vcat [text "Exception when trying to" <+> text s <+> text "compile-time code:",
                         nest 2 (text (Panic.showException exn)),
-                        nest 2 (text "Code:" <+> ppr expr)]
+                        if show_code then nest 2 (text "Code:" <+> ppr expr) else empty]
 \end{code}
 
 Note [Exceptions in TH]
@@ -539,11 +713,10 @@ like that.  Here's how it's processed:
 
   * The TcM monad is an instance of Quasi (see TcSplice), and it implements
     (qReport True s) by using addErr to add an error message to the bag of errors.
-    The 'fail' in TcM raises a UserError, with the uninteresting string
-       "IOEnv failure"
+    The 'fail' in TcM raises an IOEnvFailure exception
 
   * So, when running a splice, we catch all exceptions; then for 
-       - a UserError "IOEnv failure", we assume the error is already 
+       - an IOEnvFailure exception, we assume the error is already 
                in the error-bag (above)
        - other errors, we add an error to the bag
     and then fail
@@ -560,10 +733,14 @@ instance TH.Quasi (IOEnv (Env TcGblEnv TcLclEnv)) where
   qReport True msg  = addErr (text msg)
   qReport False msg = addReport (text msg)
 
-  qCurrentModule = do { m <- getModule;
-                        return (moduleNameString (moduleName m)) }
-                -- ToDo: is throwing away the package name ok here?
-
+  qLocation = do { m <- getModule
+                ; l <- getSrcSpanM
+                ; return (TH.Loc { TH.loc_filename = unpackFS (srcSpanFile l)
+                                 , TH.loc_module   = moduleNameString (moduleName m)
+                                 , TH.loc_package  = packageIdString (modulePackageId m)
+                                 , TH.loc_start = (srcSpanStartLine l, srcSpanStartCol l)
+                                 , TH.loc_end = (srcSpanEndLine   l, srcSpanEndCol   l) }) }
+               
   qReify v = reify v
 
        -- For qRecover, discard error messages if 
@@ -576,7 +753,7 @@ instance TH.Quasi (IOEnv (Env TcGblEnv TcLclEnv)) where
                                 Nothing  -> recover                    -- Discard all msgs
                          }
 
-  qRunIO io = ioToTcRn io
+  qRunIO io = liftIO io
 \end{code}
 
 
@@ -588,18 +765,20 @@ instance TH.Quasi (IOEnv (Env TcGblEnv TcLclEnv)) where
 
 \begin{code}
 showSplice :: String -> LHsExpr Id -> SDoc -> TcM ()
-showSplice what before after
-  = getSrcSpanM                `thenM` \ loc ->
+showSplice what before after = do
+    loc <- getSrcSpanM
     traceSplice (vcat [ppr loc <> colon <+> text "Splicing" <+> text what, 
                       nest 2 (sep [nest 2 (ppr before),
                                    text "======>",
                                    nest 2 after])])
 
+illegalBracket :: ThStage -> SDoc
 illegalBracket level
-  = ptext SLIT("Illegal bracket at level") <+> ppr level
+  = ptext (sLit "Illegal bracket at level") <+> ppr level
 
+illegalSplice :: ThStage -> SDoc
 illegalSplice level
-  = ptext SLIT("Illegal splice at level") <+> ppr level
+  = ptext (sLit "Illegal splice at level") <+> ppr level
 
 #endif         /* GHCI */
 \end{code}
@@ -626,29 +805,28 @@ reify th_name
     ppr_ns (TH.Name _ (TH.NameG TH.DataName _pkg _mod)) = text "data"
     ppr_ns (TH.Name _ (TH.NameG TH.TcClsName _pkg _mod)) = text "tc"
     ppr_ns (TH.Name _ (TH.NameG TH.VarName _pkg _mod)) = text "var"
+    ppr_ns _ = panic "reify/ppr_ns"
 
 lookupThName :: TH.Name -> TcM Name
-lookupThName th_name@(TH.Name occ flavour)
-  =  do { let rdr_name = thRdrName guessed_ns occ_str flavour
-
-       -- Repeat much of lookupOccRn, becase we want
-       -- to report errors in a TH-relevant way
-       ; rdr_env <- getLocalRdrEnv
-       ; case lookupLocalRdrEnv rdr_env rdr_name of
-           Just name -> return name
-           Nothing | not (isSrcRdrName rdr_name)       -- Exact, Orig
-                   -> lookupImportedName rdr_name
-                   | otherwise                         -- Unqual, Qual
-                   -> do { mb_name <- lookupSrcOcc_maybe rdr_name
-                         ; case mb_name of
-                             Just name -> return name
-                             Nothing   -> failWithTc (notInScope th_name) }
-       }
+lookupThName th_name = do
+    mb_name <- lookupThName_maybe th_name
+    case mb_name of
+        Nothing   -> failWithTc (notInScope th_name)
+        Just name -> return name
+
+lookupThName_maybe th_name
+  =  do { names <- mapMaybeM lookup (thRdrNameGuesses th_name)
+          -- Pick the first that works
+         -- E.g. reify (mkName "A") will pick the class A in preference to the data constructor A
+       ; return (listToMaybe names) }  
   where
-       -- guessed_ns is the name space guessed from looking at the TH name
-    guessed_ns | isLexCon (mkFastString occ_str) = OccName.dataName
-              | otherwise                       = OccName.varName
-    occ_str = TH.occString occ
+    lookup rdr_name
+       = do {  -- Repeat much of lookupOccRn, becase we want
+               -- to report errors in a TH-relevant way
+            ; rdr_env <- getLocalRdrEnv
+            ; case lookupLocalRdrEnv rdr_env rdr_name of
+                Just name -> return (Just name)
+                Nothing   -> lookupGlobalOccRn_maybe rdr_name }
 
 tcLookupTh :: Name -> TcM TcTyThing
 -- This is a specialised version of TcEnv.tcLookup; specialised mainly in that
@@ -657,7 +835,7 @@ tcLookupTh :: Name -> TcM TcTyThing
 tcLookupTh name
   = do { (gbl_env, lcl_env) <- getEnvs
        ; case lookupNameEnv (tcl_env lcl_env) name of {
-               Just thing -> returnM thing;
+               Just thing -> return thing;
                Nothing    -> do
        { if nameIsLocalOrFrom (tcg_mod gbl_env) name
          then  -- It's defined in this module
@@ -678,12 +856,12 @@ tcLookupTh name
 
 notInScope :: TH.Name -> SDoc
 notInScope th_name = quotes (text (TH.pprint th_name)) <+> 
-                    ptext SLIT("is not in scope at a reify")
+                    ptext (sLit "is not in scope at a reify")
        -- Ugh! Rather an indirect way to display the name
 
 notInEnv :: Name -> SDoc
 notInEnv name = quotes (ppr name) <+> 
-                    ptext SLIT("is not in the type environment at a reify")
+                    ptext (sLit "is not in the type environment at a reify")
 
 ------------------------------
 reifyThing :: TcTyThing -> TcM TH.Info
@@ -695,9 +873,9 @@ reifyThing (AGlobal (AnId id))
   = do { ty <- reifyType (idType id)
        ; fix <- reifyFixity (idName id)
        ; let v = reifyName id
-       ; case globalIdDetails id of
+       ; case idDetails id of
            ClassOpId cls    -> return (TH.ClassOpI v ty (reifyName cls) fix)
-           other            -> return (TH.VarI     v ty Nothing fix)
+           _                -> return (TH.VarI     v ty Nothing fix)
     }
 
 reifyThing (AGlobal (ATyCon tc))  = reifyTyCon tc
@@ -706,7 +884,9 @@ reifyThing (AGlobal (ADataCon dc))
   = do { let name = dataConName dc
        ; ty <- reifyType (idType (dataConWrapId dc))
        ; fix <- reifyFixity name
-       ; return (TH.DataConI (reifyName name) ty (reifyName (dataConTyCon dc)) fix) }
+       ; return (TH.DataConI (reifyName name) ty 
+                              (reifyName (dataConOrigTyCon dc)) fix) 
+        }
 
 reifyThing (ATcId {tct_id = id, tct_type = ty}) 
   = do { ty1 <- zonkTcType ty  -- Make use of all the info we have, even
@@ -720,16 +900,31 @@ reifyThing (ATyVar tv ty)
        ; ty2 <- reifyType ty1
        ; return (TH.TyVarI (reifyName tv) ty2) }
 
+reifyThing (AThing {}) = panic "reifyThing AThing"
+
 ------------------------------
 reifyTyCon :: TyCon -> TcM TH.Info
 reifyTyCon tc
-  | isFunTyCon tc  = return (TH.PrimTyConI (reifyName tc) 2              False)
-  | isPrimTyCon tc = return (TH.PrimTyConI (reifyName tc) (tyConArity tc) (isUnLiftedTyCon tc))
+  | isFunTyCon tc  
+  = return (TH.PrimTyConI (reifyName tc) 2               False)
+  | isPrimTyCon tc 
+  = return (TH.PrimTyConI (reifyName tc) (tyConArity tc) (isUnLiftedTyCon tc))
+  | isOpenTyCon tc
+  = let flavour = reifyFamFlavour tc
+        tvs     = tyConTyVars tc
+        kind    = tyConKind tc
+        kind'
+          | isLiftedTypeKind kind = Nothing
+          | otherwise             = Just $ reifyKind kind
+    in
+    return (TH.TyConI $
+              TH.FamilyD flavour (reifyName tc) (reifyTyVars tvs) kind')
   | isSynTyCon tc
   = do { let (tvs, rhs) = synTyConDefn tc 
        ; rhs' <- reifyType rhs
        ; return (TH.TyConI $ 
-                  TH.TySynD (reifyName tc) (reifyTyVars tvs) rhs') }
+                  TH.TySynD (reifyName tc) (reifyTyVars tvs) rhs') 
+       }
 
 reifyTyCon tc
   = do         { cxt <- reifyCxt (tyConStupidTheta tc)
@@ -739,7 +934,7 @@ reifyTyCon tc
              r_tvs  = reifyTyVars tvs
              deriv = []        -- Don't know about deriving
              decl | isNewTyCon tc = TH.NewtypeD cxt name r_tvs (head cons) deriv
-                  | otherwise     = TH.DataD    cxt name r_tvs cons      deriv
+                  | otherwise     = TH.DataD    cxt name r_tvs cons        deriv
        ; return (TH.TyConI decl) }
 
 reifyDataCon :: [Type] -> DataCon -> TcM TH.Con
@@ -761,7 +956,7 @@ reifyDataCon tys dc
          else
             return (TH.NormalC name (stricts `zip` arg_tys)) }
   | otherwise
-  = failWithTc (ptext SLIT("Can't reify a non-Haskell-98 data constructor:") 
+  = failWithTc (ptext (sLit "Can't reify a GADT data constructor:") 
                <+> quotes (ppr dc))
 
 ------------------------------
@@ -780,7 +975,6 @@ reifyClass cls
 reifyType :: TypeRep.Type -> TcM TH.Type
 reifyType (TyVarTy tv)     = return (TH.VarT (reifyName tv))
 reifyType (TyConApp tc tys) = reify_tc_app (reifyName tc) tys
-reifyType (NoteTy _ ty)     = reifyType ty
 reifyType (AppTy t1 t2)     = do { [r1,r2] <- reifyTypes [t1,t2] ; return (r1 `TH.AppT` r2) }
 reifyType (FunTy t1 t2)     = do { [r1,r2] <- reifyTypes [t1,t2] ; return (TH.ArrowT `TH.AppT` r1 `TH.AppT` r2) }
 reifyType ty@(ForAllTy _ _) = do { cxt' <- reifyCxt cxt; 
@@ -788,22 +982,59 @@ reifyType ty@(ForAllTy _ _) = do { cxt' <- reifyCxt cxt;
                                 ; return (TH.ForallT (reifyTyVars tvs) cxt' tau') }
                            where
                                (tvs, cxt, tau) = tcSplitSigmaTy ty
+reifyType (PredTy {}) = panic "reifyType PredTy"
+
+reifyTypes :: [Type] -> TcM [TH.Type]
 reifyTypes = mapM reifyType
+
+reifyKind :: Kind -> TH.Kind
+reifyKind  ki
+  = let (kis, ki') = splitKindFunTys ki
+        kis_rep    = map reifyKind kis
+        ki'_rep    = reifyNonArrowKind ki'
+    in
+    foldl TH.ArrowK ki'_rep kis_rep
+  where
+    reifyNonArrowKind k | isLiftedTypeKind k = TH.StarK
+                        | otherwise          = pprPanic "Exotic form of kind" 
+                                                        (ppr k)
+
+reifyCxt :: [PredType] -> TcM [TH.Pred]
 reifyCxt   = mapM reifyPred
 
 reifyFunDep :: ([TyVar], [TyVar]) -> TH.FunDep
 reifyFunDep (xs, ys) = TH.FunDep (map reifyName xs) (map reifyName ys)
 
-reifyTyVars :: [TyVar] -> [TH.Name]
-reifyTyVars = map reifyName
+reifyFamFlavour :: TyCon -> TH.FamFlavour
+reifyFamFlavour tc | isOpenSynTyCon tc = TH.TypeFam
+                   | isOpenTyCon    tc = TH.DataFam
+                   | otherwise         
+                   = panic "TcSplice.reifyFamFlavour: not a type family"
+
+reifyTyVars :: [TyVar] -> [TH.TyVarBndr]
+reifyTyVars = map reifyTyVar
+  where
+    reifyTyVar tv | isLiftedTypeKind kind = TH.PlainTV  name
+                  | otherwise             = TH.KindedTV name (reifyKind kind)
+      where
+        kind = tyVarKind tv
+        name = reifyName tv
 
 reify_tc_app :: TH.Name -> [TypeRep.Type] -> TcM TH.Type
 reify_tc_app tc tys = do { tys' <- reifyTypes tys 
                         ; return (foldl TH.AppT (TH.ConT tc) tys') }
 
-reifyPred :: TypeRep.PredType -> TcM TH.Type
-reifyPred (ClassP cls tys) = reify_tc_app (reifyName cls) tys
-reifyPred p@(IParam _ _)   = noTH SLIT("implicit parameters") (ppr p)
+reifyPred :: TypeRep.PredType -> TcM TH.Pred
+reifyPred (ClassP cls tys) 
+  = do { tys' <- reifyTypes tys 
+       ; return $ TH.ClassP (reifyName cls) tys'
+       }
+reifyPred p@(IParam _ _)   = noTH (sLit "implicit parameters") (ppr p)
+reifyPred (EqPred ty1 ty2) 
+  = do { ty1' <- reifyType ty1
+       ; ty2' <- reifyType ty2
+       ; return $ TH.EqualP ty1' ty2'
+       }
 
 
 ------------------------------
@@ -817,7 +1048,7 @@ reifyName thing
        -- have free variables, we may need to generate NameL's for them.
   where
     name    = getName thing
-    mod     = nameModule name
+    mod     = ASSERT( isExternalName name ) nameModule name
     pkg_str = packageIdString (modulePackageId mod)
     mod_str = moduleNameString (moduleName mod)
     occ_str = occNameString occ
@@ -845,7 +1076,7 @@ reifyStrict NotMarkedStrict = TH.NotStrict
 
 ------------------------------
 noTH :: LitString -> SDoc -> TcM a
-noTH s d = failWithTc (hsep [ptext SLIT("Can't represent") <+> ptext s <+> 
-                               ptext SLIT("in Template Haskell:"),
+noTH s d = failWithTc (hsep [ptext (sLit "Can't represent") <+> ptext s <+> 
+                               ptext (sLit "in Template Haskell:"),
                             nest 2 d])
 \end{code}