import HsSyn ( HsBracket(..), HsExpr(..), HsSplice(..), LHsExpr, LHsDecl,
HsType, LHsType )
-import Convert ( convertToHsExpr, convertToHsDecls, convertToHsType )
+import Convert ( convertToHsExpr, convertToHsDecls, convertToHsType, thRdrName )
import RnExpr ( rnLExpr )
-import RnEnv ( lookupFixityRn, lookupSrcOcc_maybe )
-import RdrName ( RdrName, mkRdrUnqual, lookupLocalRdrEnv )
+import RnEnv ( lookupFixityRn, lookupSrcOcc_maybe, lookupImportedName )
+import RdrName ( RdrName, lookupLocalRdrEnv, isSrcRdrName )
import RnTypes ( rnLHsType )
import TcExpr ( tcCheckRho, tcMonoExpr )
-import TcHsSyn ( mkHsLet, zonkTopLExpr )
+import TcHsSyn ( mkHsDictLet, zonkTopLExpr )
import TcSimplify ( tcSimplifyTop, tcSimplifyBracket )
import TcUnify ( Expected, zapExpectedTo, zapExpectedType )
import TcType ( TcType, TcKind, liftedTypeKind, mkAppTy, tcSplitSigmaTy )
import TcEnv ( spliceOK, tcMetaTy, bracketOK )
-import TcMType ( newTyFlexiVarTy, newKindVar, UserTypeCtxt(ExprSigCtxt), zonkTcType, zonkTcTyVar )
+import TcMType ( newTyFlexiVarTy, newKindVar, UserTypeCtxt(ExprSigCtxt), zonkTcType )
import TcHsType ( tcHsSigType, kcHsType )
import TcIface ( tcImportDecl )
import TypeRep ( Type(..), PredType(..), TyThing(..) ) -- For reification
import Name ( Name, NamedThing(..), nameOccName, nameModule, isExternalName,
- mkInternalName, nameIsLocalOrFrom )
+ nameIsLocalOrFrom )
import NameEnv ( lookupNameEnv )
-import HscTypes ( lookupType, ExternalPackageState(..) )
+import HscTypes ( lookupType, ExternalPackageState(..), emptyModDetails )
import OccName
import Var ( Id, TyVar, idType )
-import Module ( moduleUserString, mkModule )
+import Module ( moduleUserString )
import TcRnMonad
import IfaceEnv ( lookupOrig )
import Class ( Class, classExtraBigSig )
-import TyCon ( TyCon, AlgTyConRhs(..), tyConTyVars, getSynTyConDefn,
- isSynTyCon, isNewTyCon, tyConDataCons, algTyConRhs, isPrimTyCon, isFunTyCon,
- tyConArity, isUnLiftedTyCon )
+import TyCon ( TyCon, tyConTyVars, getSynTyConDefn,
+ isSynTyCon, isNewTyCon, tyConDataCons, isPrimTyCon, isFunTyCon,
+ tyConArity, tyConStupidTheta, isUnLiftedTyCon )
import DataCon ( DataCon, dataConTyCon, dataConOrigArgTys, dataConStrictMarks,
dataConName, dataConFieldLabels, dataConWrapId, dataConIsInfix,
isVanillaDataCon )
import TysWiredIn ( mkListTy )
import DsMeta ( expQTyConName, typeQTyConName, decTyConName, qTyConName, nameTyConName )
import ErrUtils ( Message )
-import SrcLoc ( noLoc, unLoc, getLoc, noSrcLoc )
+import SrcLoc ( noLoc, unLoc, getLoc )
import Outputable
import Unique ( Unique, Uniquable(..), getKey, mkUniqueGrimily )
import GHC.Base ( unsafeCoerce#, Int#, Int(..) ) -- Should have a better home in the module hierarchy
import Monad ( liftM )
-import Maybes ( orElse )
#ifdef GHCI
import FastString ( mkFastString )
tc_bracket :: HsBracket Name -> TcM TcType
tc_bracket (VarBr v)
- = tcMetaTy nameTyConName
- -- Result type is Var (not Q-monadic)
+ = tcMetaTy nameTyConName -- Result type is Var (not Q-monadic)
tc_bracket (ExpBr expr)
= newTyFlexiVarTy liftedTypeKind `thenM` \ any_ty ->
-- Result type is Type (= Q Typ)
tc_bracket (DecBr decls)
- = tcTopSrcDecls [{- no boot-names -}] decls `thenM_`
+ = do { tcTopSrcDecls emptyModDetails decls
-- Typecheck the declarations, dicarding the result
-- We'll get all that stuff later, when we splice it in
- tcMetaTy decTyConName `thenM` \ decl_ty ->
- tcMetaTy qTyConName `thenM` \ q_ty ->
- returnM (mkAppTy q_ty (mkListTy decl_ty))
+ ; decl_ty <- tcMetaTy decTyConName
+ ; q_ty <- tcMetaTy qTyConName
+ ; return (mkAppTy q_ty (mkListTy decl_ty))
-- Result type is Q [Dec]
+ }
\end{code}
-- simple_expr :: TH.Exp
expr2 :: LHsExpr RdrName
- expr2 = convertToHsExpr simple_expr
+ expr2 = convertToHsExpr (getLoc expr) simple_expr
in
traceTc (text "Got result" <+> ppr expr2) `thenM_`
; const_binds <- tcSimplifyTop lie
-- And zonk it
- ; zonkTopLExpr (mkHsLet const_binds expr') }
+ ; zonkTopLExpr (mkHsDictLet const_binds expr') }
\end{code}
; let -- simple_ty :: TH.Type
hs_ty2 :: LHsType RdrName
- hs_ty2 = convertToHsType simple_ty
+ hs_ty2 = convertToHsType (getLoc expr) simple_ty
; traceTc (text "Got result" <+> ppr hs_ty2)
\begin{code}
-- Always at top level
+-- Type sig at top of file:
+-- tcSpliceDecls :: LHsExpr Name -> TcM [LHsDecl RdrName]
tcSpliceDecls expr
= do { meta_dec_ty <- tcMetaTy decTyConName
; meta_q_ty <- tcMetaTy qTyConName
-- simple_expr :: [TH.Dec]
-- decls :: [RdrNameHsDecl]
- ; decls <- handleErrors (convertToHsDecls simple_expr)
+ ; decls <- handleErrors (convertToHsDecls (getLoc expr) simple_expr)
; traceTc (text "Got result" <+> vcat (map ppr decls))
; showSplice "declarations"
- zonked_q_expr (vcat (map ppr decls))
+ zonked_q_expr
+ (ppr (getLoc expr) $$ (vcat (map ppr decls)))
; returnM decls }
where handleErrors :: [Either a Message] -> TcM [a]
; this_mod <- getModule
; let type_env = tcg_type_env tcg_env
rdr_env = tcg_rdr_env tcg_env
- -- Wrap the compile-and-run in an exception-catcher
- -- Compiling might fail if linking fails
- -- Running might fail if it throws an exception
- ; either_tval <- tryM $ do
- { -- Compile it
- hval <- ioToTcRn (HscMain.compileExpr
+
+ -- Compile and link it; might fail if linking fails
+ ; either_hval <- tryM $ ioToTcRn $
+ HscMain.compileExpr
hsc_env this_mod
- rdr_env type_env expr)
- -- Coerce it to Q t, and run it
- ; TH.runQ (unsafeCoerce# hval) }
+ rdr_env type_env expr
+ ; case either_hval of {
+ Left exn -> failWithTc (mk_msg "compile and link" exn) ;
+ Right hval -> do
+
+ { -- Coerce it to Q t, and run it
+ -- Running might fail if it throws an exception of any kind (hence tryAllM)
+ -- including, say, a pattern-match exception in the code we are running
+ either_tval <- tryAllM (TH.runQ (unsafeCoerce# hval))
; case either_tval of
- Left exn -> failWithTc (vcat [text "Exception when trying to run compile-time code:",
- nest 4 (vcat [text "Code:" <+> ppr expr,
- text ("Exn: " ++ Panic.showException exn)])])
- Right v -> returnM v }
+ Left exn -> failWithTc (mk_msg "run" exn)
+ Right v -> returnM v
+ }}}
+ 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)]
\end{code}
To call runQ in the Tc monad, we need to make TcM an instance of Quasi:
; thing <- tcLookupTh name
-- ToDo: this tcLookup could fail, which would give a
-- rather unhelpful error message
+ ; traceIf (text "reify" <+> text (show th_name) <+> brackets (ppr_ns th_name) <+> ppr name)
; reifyThing thing
}
+ where
+ ppr_ns (TH.Name _ (TH.NameG TH.DataName mod)) = text "data"
+ ppr_ns (TH.Name _ (TH.NameG TH.TcClsName mod)) = text "tc"
+ ppr_ns (TH.Name _ (TH.NameG TH.VarName mod)) = text "var"
lookupThName :: TH.Name -> TcM Name
-lookupThName (TH.Name occ (TH.NameG th_ns mod))
- = lookupOrig (mkModule (TH.modString mod))
- (OccName.mkOccName ghc_ns (TH.occString occ))
- where
- ghc_ns = case th_ns of
- TH.DataName -> dataName
- TH.TcClsName -> tcClsName
- TH.VarName -> varName
+lookupThName th_name
+ = do { let rdr_name = thRdrName guessed_ns th_name
-lookupThName th_name@(TH.Name occ TH.NameS)
- = do { let rdr_name = mkRdrUnqual (OccName.mkOccFS ns occ_fs)
+ -- 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 -> do
- { mb_name <- lookupSrcOcc_maybe rdr_name
- ; case mb_name of
- Just name -> return name ;
- Nothing -> failWithTc (notInScope th_name)
- }}
- where
- ns | isLexCon occ_fs = OccName.dataName
- | otherwise = OccName.varName
- occ_fs = mkFastString (TH.occString occ)
-
-lookupThName (TH.Name occ (TH.NameU uniq))
- = return (mkInternalName (mk_uniq uniq) (OccName.mkOccFS bogus_ns occ_fs) noSrcLoc)
+ 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) }
+ }
where
- occ_fs = mkFastString (TH.occString occ)
- bogus_ns = OccName.varName -- Not yet recorded in the TH name
- -- but only the unique matters
+ -- guessed_ns is the name space guessed from looking at the TH name
+ guessed_ns | isLexCon occ_fs = OccName.dataName
+ | otherwise = OccName.varName
+ occ_fs = mkFastString (TH.nameBase th_name)
tcLookupTh :: Name -> TcM TcTyThing
-- This is a specialised version of TcEnv.tcLookup; specialised mainly in that
-- tcLookup, failure is a bug.
tcLookupTh name
= do { (gbl_env, lcl_env) <- getEnvs
- ; case lookupNameEnv (tcl_env lcl_env) name of
- Just thing -> returnM thing
+ ; case lookupNameEnv (tcl_env lcl_env) name of {
+ Just thing -> returnM thing;
Nothing -> do
{ if nameIsLocalOrFrom (tcg_mod gbl_env) name
then -- It's defined in this module
{ (eps,hpt) <- getEpsAndHpt
; case lookupType hpt (eps_PTE eps) name of
Just thing -> return (AGlobal thing)
- Nothing -> do { traceIf (text "tcLookupGlobal" <+> ppr name)
- ; thing <- initIfaceTcRn (tcImportDecl name)
+ Nothing -> do { thing <- tcImportDecl name
; return (AGlobal thing) }
-- Imported names should always be findable;
-- if not, we fail hard in tcImportDecl
- }}}
-
-mk_uniq :: Int# -> Unique
-mk_uniq u = mkUniqueGrimily (I# u)
+ }}}}
notInScope :: TH.Name -> SDoc
notInScope th_name = quotes (text (TH.pprint th_name)) <+>
; fix <- reifyFixity name
; return (TH.DataConI (reifyName name) ty (reifyName (dataConTyCon dc)) fix) }
-reifyThing (ATcId id _ _)
+reifyThing (ATcId id _)
= do { ty1 <- zonkTcType (idType id) -- Make use of all the info we have, even
-- though it may be incomplete
; ty2 <- reifyType ty1
; return (TH.TyConI $ TH.TySynD (reifyName tc) (reifyTyVars tvs) rhs') }
reifyTyCon tc
- = case algTyConRhs tc of
- NewTyCon data_con _ _
- -> do { con <- reifyDataCon data_con
- ; return (TH.TyConI $ TH.NewtypeD [] (reifyName tc) (reifyTyVars (tyConTyVars tc))
- con [{- Don't know about deriving -}]) }
-
- DataTyCon mb_cxt cons _
- -> do { cxt <- reifyCxt (mb_cxt `orElse` [])
- ; cons <- mapM reifyDataCon (tyConDataCons tc)
- ; return (TH.TyConI $ TH.DataD cxt (reifyName tc) (reifyTyVars (tyConTyVars tc))
- cons [{- Don't know about deriving -}]) }
+ = do { cxt <- reifyCxt (tyConStupidTheta tc)
+ ; cons <- mapM reifyDataCon (tyConDataCons tc)
+ ; let name = reifyName tc
+ tvs = reifyTyVars (tyConTyVars tc)
+ deriv = [] -- Don't know about deriving
+ decl | isNewTyCon tc = TH.NewtypeD cxt name tvs (head cons) deriv
+ | otherwise = TH.DataD cxt name tvs cons deriv
+ ; return (TH.TyConI decl) }
reifyDataCon :: DataCon -> TcM TH.Con
reifyDataCon dc
else
if dataConIsInfix dc then
ASSERT( length arg_tys == 2 )
- return (TH.InfixC (s1,a1) name (s1,a2))
+ return (TH.InfixC (s1,a1) name (s2,a2))
else
return (TH.NormalC name (stricts `zip` arg_tys)) }
| otherwise
reifyName thing
| isExternalName name = mk_varg mod occ_str
| otherwise = TH.mkNameU occ_str (getKey (getUnique name))
+ -- Many of the things we reify have local bindings, and
+ -- NameL's aren't supposed to appear in binding positions, so
+ -- we use NameU. When/if we start to reify nested things, that
+ -- have free variables, we may need to generate NameL's for them.
where
name = getName thing
mod = moduleUserString (nameModule name)