summaryrefslogtreecommitdiff
path: root/libraries/template-haskell/Language/Haskell/TH
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/template-haskell/Language/Haskell/TH')
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Lib.hs671
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Lib/Map.hs108
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Ppr.hs568
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/PprLib.hs227
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Quote.hs87
-rw-r--r--libraries/template-haskell/Language/Haskell/TH/Syntax.hs1457
6 files changed, 3118 insertions, 0 deletions
diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib.hs b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
new file mode 100644
index 0000000000..3ac16d1dba
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/Lib.hs
@@ -0,0 +1,671 @@
+-- |
+-- TH.Lib contains lots of useful helper functions for
+-- generating and manipulating Template Haskell terms
+
+module Language.Haskell.TH.Lib where
+ -- All of the exports from this module should
+ -- be "public" functions. The main module TH
+ -- re-exports them all.
+
+import Language.Haskell.TH.Syntax hiding (Role)
+import qualified Language.Haskell.TH.Syntax as TH
+import Control.Monad( liftM, liftM2 )
+import Data.Word( Word8 )
+
+----------------------------------------------------------
+-- * Type synonyms
+----------------------------------------------------------
+
+type InfoQ = Q Info
+type PatQ = Q Pat
+type FieldPatQ = Q FieldPat
+type ExpQ = Q Exp
+type TExpQ a = Q (TExp a)
+type DecQ = Q Dec
+type DecsQ = Q [Dec]
+type ConQ = Q Con
+type TypeQ = Q Type
+type TyLitQ = Q TyLit
+type CxtQ = Q Cxt
+type PredQ = Q Pred
+type MatchQ = Q Match
+type ClauseQ = Q Clause
+type BodyQ = Q Body
+type GuardQ = Q Guard
+type StmtQ = Q Stmt
+type RangeQ = Q Range
+type StrictTypeQ = Q StrictType
+type VarStrictTypeQ = Q VarStrictType
+type FieldExpQ = Q FieldExp
+type RuleBndrQ = Q RuleBndr
+type TySynEqnQ = Q TySynEqn
+type Role = TH.Role -- must be defined here for DsMeta to find it
+
+----------------------------------------------------------
+-- * Lowercase pattern syntax functions
+----------------------------------------------------------
+
+intPrimL :: Integer -> Lit
+intPrimL = IntPrimL
+wordPrimL :: Integer -> Lit
+wordPrimL = WordPrimL
+floatPrimL :: Rational -> Lit
+floatPrimL = FloatPrimL
+doublePrimL :: Rational -> Lit
+doublePrimL = DoublePrimL
+integerL :: Integer -> Lit
+integerL = IntegerL
+charL :: Char -> Lit
+charL = CharL
+stringL :: String -> Lit
+stringL = StringL
+stringPrimL :: [Word8] -> Lit
+stringPrimL = StringPrimL
+rationalL :: Rational -> Lit
+rationalL = RationalL
+
+litP :: Lit -> PatQ
+litP l = return (LitP l)
+varP :: Name -> PatQ
+varP v = return (VarP v)
+tupP :: [PatQ] -> PatQ
+tupP ps = do { ps1 <- sequence ps; return (TupP ps1)}
+unboxedTupP :: [PatQ] -> PatQ
+unboxedTupP ps = do { ps1 <- sequence ps; return (UnboxedTupP ps1)}
+conP :: Name -> [PatQ] -> PatQ
+conP n ps = do ps' <- sequence ps
+ return (ConP n ps')
+infixP :: PatQ -> Name -> PatQ -> PatQ
+infixP p1 n p2 = do p1' <- p1
+ p2' <- p2
+ return (InfixP p1' n p2')
+uInfixP :: PatQ -> Name -> PatQ -> PatQ
+uInfixP p1 n p2 = do p1' <- p1
+ p2' <- p2
+ return (UInfixP p1' n p2')
+parensP :: PatQ -> PatQ
+parensP p = do p' <- p
+ return (ParensP p')
+
+tildeP :: PatQ -> PatQ
+tildeP p = do p' <- p
+ return (TildeP p')
+bangP :: PatQ -> PatQ
+bangP p = do p' <- p
+ return (BangP p')
+asP :: Name -> PatQ -> PatQ
+asP n p = do p' <- p
+ return (AsP n p')
+wildP :: PatQ
+wildP = return WildP
+recP :: Name -> [FieldPatQ] -> PatQ
+recP n fps = do fps' <- sequence fps
+ return (RecP n fps')
+listP :: [PatQ] -> PatQ
+listP ps = do ps' <- sequence ps
+ return (ListP ps')
+sigP :: PatQ -> TypeQ -> PatQ
+sigP p t = do p' <- p
+ t' <- t
+ return (SigP p' t')
+viewP :: ExpQ -> PatQ -> PatQ
+viewP e p = do e' <- e
+ p' <- p
+ return (ViewP e' p')
+
+fieldPat :: Name -> PatQ -> FieldPatQ
+fieldPat n p = do p' <- p
+ return (n, p')
+
+
+-------------------------------------------------------------------------------
+-- * Stmt
+
+bindS :: PatQ -> ExpQ -> StmtQ
+bindS p e = liftM2 BindS p e
+
+letS :: [DecQ] -> StmtQ
+letS ds = do { ds1 <- sequence ds; return (LetS ds1) }
+
+noBindS :: ExpQ -> StmtQ
+noBindS e = do { e1 <- e; return (NoBindS e1) }
+
+parS :: [[StmtQ]] -> StmtQ
+parS sss = do { sss1 <- mapM sequence sss; return (ParS sss1) }
+
+-------------------------------------------------------------------------------
+-- * Range
+
+fromR :: ExpQ -> RangeQ
+fromR x = do { a <- x; return (FromR a) }
+
+fromThenR :: ExpQ -> ExpQ -> RangeQ
+fromThenR x y = do { a <- x; b <- y; return (FromThenR a b) }
+
+fromToR :: ExpQ -> ExpQ -> RangeQ
+fromToR x y = do { a <- x; b <- y; return (FromToR a b) }
+
+fromThenToR :: ExpQ -> ExpQ -> ExpQ -> RangeQ
+fromThenToR x y z = do { a <- x; b <- y; c <- z;
+ return (FromThenToR a b c) }
+-------------------------------------------------------------------------------
+-- * Body
+
+normalB :: ExpQ -> BodyQ
+normalB e = do { e1 <- e; return (NormalB e1) }
+
+guardedB :: [Q (Guard,Exp)] -> BodyQ
+guardedB ges = do { ges' <- sequence ges; return (GuardedB ges') }
+
+-------------------------------------------------------------------------------
+-- * Guard
+
+normalG :: ExpQ -> GuardQ
+normalG e = do { e1 <- e; return (NormalG e1) }
+
+normalGE :: ExpQ -> ExpQ -> Q (Guard, Exp)
+normalGE g e = do { g1 <- g; e1 <- e; return (NormalG g1, e1) }
+
+patG :: [StmtQ] -> GuardQ
+patG ss = do { ss' <- sequence ss; return (PatG ss') }
+
+patGE :: [StmtQ] -> ExpQ -> Q (Guard, Exp)
+patGE ss e = do { ss' <- sequence ss;
+ e' <- e;
+ return (PatG ss', e') }
+
+-------------------------------------------------------------------------------
+-- * Match and Clause
+
+-- | Use with 'caseE'
+match :: PatQ -> BodyQ -> [DecQ] -> MatchQ
+match p rhs ds = do { p' <- p;
+ r' <- rhs;
+ ds' <- sequence ds;
+ return (Match p' r' ds') }
+
+-- | Use with 'funD'
+clause :: [PatQ] -> BodyQ -> [DecQ] -> ClauseQ
+clause ps r ds = do { ps' <- sequence ps;
+ r' <- r;
+ ds' <- sequence ds;
+ return (Clause ps' r' ds') }
+
+
+---------------------------------------------------------------------------
+-- * Exp
+
+-- | Dynamically binding a variable (unhygenic)
+dyn :: String -> ExpQ
+dyn s = return (VarE (mkName s))
+
+global :: Name -> ExpQ
+{-# DEPRECATED global "Use varE instead" #-}
+-- Trac #8656; I have no idea why this function is duplicated
+global s = return (VarE s)
+
+varE :: Name -> ExpQ
+varE s = return (VarE s)
+
+conE :: Name -> ExpQ
+conE s = return (ConE s)
+
+litE :: Lit -> ExpQ
+litE c = return (LitE c)
+
+appE :: ExpQ -> ExpQ -> ExpQ
+appE x y = do { a <- x; b <- y; return (AppE a b)}
+
+parensE :: ExpQ -> ExpQ
+parensE x = do { x' <- x; return (ParensE x') }
+
+uInfixE :: ExpQ -> ExpQ -> ExpQ -> ExpQ
+uInfixE x s y = do { x' <- x; s' <- s; y' <- y;
+ return (UInfixE x' s' y') }
+
+infixE :: Maybe ExpQ -> ExpQ -> Maybe ExpQ -> ExpQ
+infixE (Just x) s (Just y) = do { a <- x; s' <- s; b <- y;
+ return (InfixE (Just a) s' (Just b))}
+infixE Nothing s (Just y) = do { s' <- s; b <- y;
+ return (InfixE Nothing s' (Just b))}
+infixE (Just x) s Nothing = do { a <- x; s' <- s;
+ return (InfixE (Just a) s' Nothing)}
+infixE Nothing s Nothing = do { s' <- s; return (InfixE Nothing s' Nothing) }
+
+infixApp :: ExpQ -> ExpQ -> ExpQ -> ExpQ
+infixApp x y z = infixE (Just x) y (Just z)
+sectionL :: ExpQ -> ExpQ -> ExpQ
+sectionL x y = infixE (Just x) y Nothing
+sectionR :: ExpQ -> ExpQ -> ExpQ
+sectionR x y = infixE Nothing x (Just y)
+
+lamE :: [PatQ] -> ExpQ -> ExpQ
+lamE ps e = do ps' <- sequence ps
+ e' <- e
+ return (LamE ps' e')
+
+-- | Single-arg lambda
+lam1E :: PatQ -> ExpQ -> ExpQ
+lam1E p e = lamE [p] e
+
+lamCaseE :: [MatchQ] -> ExpQ
+lamCaseE ms = sequence ms >>= return . LamCaseE
+
+tupE :: [ExpQ] -> ExpQ
+tupE es = do { es1 <- sequence es; return (TupE es1)}
+
+unboxedTupE :: [ExpQ] -> ExpQ
+unboxedTupE es = do { es1 <- sequence es; return (UnboxedTupE es1)}
+
+condE :: ExpQ -> ExpQ -> ExpQ -> ExpQ
+condE x y z = do { a <- x; b <- y; c <- z; return (CondE a b c)}
+
+multiIfE :: [Q (Guard, Exp)] -> ExpQ
+multiIfE alts = sequence alts >>= return . MultiIfE
+
+letE :: [DecQ] -> ExpQ -> ExpQ
+letE ds e = do { ds2 <- sequence ds; e2 <- e; return (LetE ds2 e2) }
+
+caseE :: ExpQ -> [MatchQ] -> ExpQ
+caseE e ms = do { e1 <- e; ms1 <- sequence ms; return (CaseE e1 ms1) }
+
+doE :: [StmtQ] -> ExpQ
+doE ss = do { ss1 <- sequence ss; return (DoE ss1) }
+
+compE :: [StmtQ] -> ExpQ
+compE ss = do { ss1 <- sequence ss; return (CompE ss1) }
+
+arithSeqE :: RangeQ -> ExpQ
+arithSeqE r = do { r' <- r; return (ArithSeqE r') }
+
+listE :: [ExpQ] -> ExpQ
+listE es = do { es1 <- sequence es; return (ListE es1) }
+
+sigE :: ExpQ -> TypeQ -> ExpQ
+sigE e t = do { e1 <- e; t1 <- t; return (SigE e1 t1) }
+
+recConE :: Name -> [Q (Name,Exp)] -> ExpQ
+recConE c fs = do { flds <- sequence fs; return (RecConE c flds) }
+
+recUpdE :: ExpQ -> [Q (Name,Exp)] -> ExpQ
+recUpdE e fs = do { e1 <- e; flds <- sequence fs; return (RecUpdE e1 flds) }
+
+stringE :: String -> ExpQ
+stringE = litE . stringL
+
+fieldExp :: Name -> ExpQ -> Q (Name, Exp)
+fieldExp s e = do { e' <- e; return (s,e') }
+
+-- ** 'arithSeqE' Shortcuts
+fromE :: ExpQ -> ExpQ
+fromE x = do { a <- x; return (ArithSeqE (FromR a)) }
+
+fromThenE :: ExpQ -> ExpQ -> ExpQ
+fromThenE x y = do { a <- x; b <- y; return (ArithSeqE (FromThenR a b)) }
+
+fromToE :: ExpQ -> ExpQ -> ExpQ
+fromToE x y = do { a <- x; b <- y; return (ArithSeqE (FromToR a b)) }
+
+fromThenToE :: ExpQ -> ExpQ -> ExpQ -> ExpQ
+fromThenToE x y z = do { a <- x; b <- y; c <- z;
+ return (ArithSeqE (FromThenToR a b c)) }
+
+
+-------------------------------------------------------------------------------
+-- * Dec
+
+valD :: PatQ -> BodyQ -> [DecQ] -> DecQ
+valD p b ds =
+ do { p' <- p
+ ; ds' <- sequence ds
+ ; b' <- b
+ ; return (ValD p' b' ds')
+ }
+
+funD :: Name -> [ClauseQ] -> DecQ
+funD nm cs =
+ do { cs1 <- sequence cs
+ ; return (FunD nm cs1)
+ }
+
+tySynD :: Name -> [TyVarBndr] -> TypeQ -> DecQ
+tySynD tc tvs rhs = do { rhs1 <- rhs; return (TySynD tc tvs rhs1) }
+
+dataD :: CxtQ -> Name -> [TyVarBndr] -> [ConQ] -> [Name] -> DecQ
+dataD ctxt tc tvs cons derivs =
+ do
+ ctxt1 <- ctxt
+ cons1 <- sequence cons
+ return (DataD ctxt1 tc tvs cons1 derivs)
+
+newtypeD :: CxtQ -> Name -> [TyVarBndr] -> ConQ -> [Name] -> DecQ
+newtypeD ctxt tc tvs con derivs =
+ do
+ ctxt1 <- ctxt
+ con1 <- con
+ return (NewtypeD ctxt1 tc tvs con1 derivs)
+
+classD :: CxtQ -> Name -> [TyVarBndr] -> [FunDep] -> [DecQ] -> DecQ
+classD ctxt cls tvs fds decs =
+ do
+ decs1 <- sequence decs
+ ctxt1 <- ctxt
+ return $ ClassD ctxt1 cls tvs fds decs1
+
+instanceD :: CxtQ -> TypeQ -> [DecQ] -> DecQ
+instanceD ctxt ty decs =
+ do
+ ctxt1 <- ctxt
+ decs1 <- sequence decs
+ ty1 <- ty
+ return $ InstanceD ctxt1 ty1 decs1
+
+sigD :: Name -> TypeQ -> DecQ
+sigD fun ty = liftM (SigD fun) $ ty
+
+forImpD :: Callconv -> Safety -> String -> Name -> TypeQ -> DecQ
+forImpD cc s str n ty
+ = do ty' <- ty
+ return $ ForeignD (ImportF cc s str n ty')
+
+infixLD :: Int -> Name -> DecQ
+infixLD prec nm = return (InfixD (Fixity prec InfixL) nm)
+
+infixRD :: Int -> Name -> DecQ
+infixRD prec nm = return (InfixD (Fixity prec InfixR) nm)
+
+infixND :: Int -> Name -> DecQ
+infixND prec nm = return (InfixD (Fixity prec InfixN) nm)
+
+pragInlD :: Name -> Inline -> RuleMatch -> Phases -> DecQ
+pragInlD name inline rm phases
+ = return $ PragmaD $ InlineP name inline rm phases
+
+pragSpecD :: Name -> TypeQ -> Phases -> DecQ
+pragSpecD n ty phases
+ = do
+ ty1 <- ty
+ return $ PragmaD $ SpecialiseP n ty1 Nothing phases
+
+pragSpecInlD :: Name -> TypeQ -> Inline -> Phases -> DecQ
+pragSpecInlD n ty inline phases
+ = do
+ ty1 <- ty
+ return $ PragmaD $ SpecialiseP n ty1 (Just inline) phases
+
+pragSpecInstD :: TypeQ -> DecQ
+pragSpecInstD ty
+ = do
+ ty1 <- ty
+ return $ PragmaD $ SpecialiseInstP ty1
+
+pragRuleD :: String -> [RuleBndrQ] -> ExpQ -> ExpQ -> Phases -> DecQ
+pragRuleD n bndrs lhs rhs phases
+ = do
+ bndrs1 <- sequence bndrs
+ lhs1 <- lhs
+ rhs1 <- rhs
+ return $ PragmaD $ RuleP n bndrs1 lhs1 rhs1 phases
+
+pragAnnD :: AnnTarget -> ExpQ -> DecQ
+pragAnnD target expr
+ = do
+ exp1 <- expr
+ return $ PragmaD $ AnnP target exp1
+
+familyNoKindD :: FamFlavour -> Name -> [TyVarBndr] -> DecQ
+familyNoKindD flav tc tvs = return $ FamilyD flav tc tvs Nothing
+
+familyKindD :: FamFlavour -> Name -> [TyVarBndr] -> Kind -> DecQ
+familyKindD flav tc tvs k = return $ FamilyD flav tc tvs (Just k)
+
+dataInstD :: CxtQ -> Name -> [TypeQ] -> [ConQ] -> [Name] -> DecQ
+dataInstD ctxt tc tys cons derivs =
+ do
+ ctxt1 <- ctxt
+ tys1 <- sequence tys
+ cons1 <- sequence cons
+ return (DataInstD ctxt1 tc tys1 cons1 derivs)
+
+newtypeInstD :: CxtQ -> Name -> [TypeQ] -> ConQ -> [Name] -> DecQ
+newtypeInstD ctxt tc tys con derivs =
+ do
+ ctxt1 <- ctxt
+ tys1 <- sequence tys
+ con1 <- con
+ return (NewtypeInstD ctxt1 tc tys1 con1 derivs)
+
+tySynInstD :: Name -> TySynEqnQ -> DecQ
+tySynInstD tc eqn =
+ do
+ eqn1 <- eqn
+ return (TySynInstD tc eqn1)
+
+closedTypeFamilyNoKindD :: Name -> [TyVarBndr] -> [TySynEqnQ] -> DecQ
+closedTypeFamilyNoKindD tc tvs eqns =
+ do
+ eqns1 <- sequence eqns
+ return (ClosedTypeFamilyD tc tvs Nothing eqns1)
+
+closedTypeFamilyKindD :: Name -> [TyVarBndr] -> Kind -> [TySynEqnQ] -> DecQ
+closedTypeFamilyKindD tc tvs kind eqns =
+ do
+ eqns1 <- sequence eqns
+ return (ClosedTypeFamilyD tc tvs (Just kind) eqns1)
+
+roleAnnotD :: Name -> [Role] -> DecQ
+roleAnnotD name roles = return $ RoleAnnotD name roles
+
+tySynEqn :: [TypeQ] -> TypeQ -> TySynEqnQ
+tySynEqn lhs rhs =
+ do
+ lhs1 <- sequence lhs
+ rhs1 <- rhs
+ return (TySynEqn lhs1 rhs1)
+
+cxt :: [PredQ] -> CxtQ
+cxt = sequence
+
+normalC :: Name -> [StrictTypeQ] -> ConQ
+normalC con strtys = liftM (NormalC con) $ sequence strtys
+
+recC :: Name -> [VarStrictTypeQ] -> ConQ
+recC con varstrtys = liftM (RecC con) $ sequence varstrtys
+
+infixC :: Q (Strict, Type) -> Name -> Q (Strict, Type) -> ConQ
+infixC st1 con st2 = do st1' <- st1
+ st2' <- st2
+ return $ InfixC st1' con st2'
+
+forallC :: [TyVarBndr] -> CxtQ -> ConQ -> ConQ
+forallC ns ctxt con = liftM2 (ForallC ns) ctxt con
+
+
+-------------------------------------------------------------------------------
+-- * Type
+
+forallT :: [TyVarBndr] -> CxtQ -> TypeQ -> TypeQ
+forallT tvars ctxt ty = do
+ ctxt1 <- ctxt
+ ty1 <- ty
+ return $ ForallT tvars ctxt1 ty1
+
+varT :: Name -> TypeQ
+varT = return . VarT
+
+conT :: Name -> TypeQ
+conT = return . ConT
+
+appT :: TypeQ -> TypeQ -> TypeQ
+appT t1 t2 = do
+ t1' <- t1
+ t2' <- t2
+ return $ AppT t1' t2'
+
+arrowT :: TypeQ
+arrowT = return ArrowT
+
+listT :: TypeQ
+listT = return ListT
+
+litT :: TyLitQ -> TypeQ
+litT l = fmap LitT l
+
+tupleT :: Int -> TypeQ
+tupleT i = return (TupleT i)
+
+unboxedTupleT :: Int -> TypeQ
+unboxedTupleT i = return (UnboxedTupleT i)
+
+sigT :: TypeQ -> Kind -> TypeQ
+sigT t k
+ = do
+ t' <- t
+ return $ SigT t' k
+
+equalityT :: TypeQ
+equalityT = return EqualityT
+
+{-# DEPRECATED classP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please use 'conT' and 'appT'." #-}
+classP :: Name -> [Q Type] -> Q Pred
+classP cla tys
+ = do
+ tysl <- sequence tys
+ return (foldl AppT (ConT cla) tysl)
+
+{-# DEPRECATED equalP "As of template-haskell-2.10, constraint predicates (Pred) are just types (Type), in keeping with ConstraintKinds. Please see 'equalityT'." #-}
+equalP :: TypeQ -> TypeQ -> PredQ
+equalP tleft tright
+ = do
+ tleft1 <- tleft
+ tright1 <- tright
+ eqT <- equalityT
+ return (foldl AppT eqT [tleft1, tright1])
+
+promotedT :: Name -> TypeQ
+promotedT = return . PromotedT
+
+promotedTupleT :: Int -> TypeQ
+promotedTupleT i = return (PromotedTupleT i)
+
+promotedNilT :: TypeQ
+promotedNilT = return PromotedNilT
+
+promotedConsT :: TypeQ
+promotedConsT = return PromotedConsT
+
+isStrict, notStrict, unpacked :: Q Strict
+isStrict = return $ IsStrict
+notStrict = return $ NotStrict
+unpacked = return Unpacked
+
+strictType :: Q Strict -> TypeQ -> StrictTypeQ
+strictType = liftM2 (,)
+
+varStrictType :: Name -> StrictTypeQ -> VarStrictTypeQ
+varStrictType v st = do (s, t) <- st
+ return (v, s, t)
+
+-- * Type Literals
+
+numTyLit :: Integer -> TyLitQ
+numTyLit n = if n >= 0 then return (NumTyLit n)
+ else fail ("Negative type-level number: " ++ show n)
+
+strTyLit :: String -> TyLitQ
+strTyLit s = return (StrTyLit s)
+
+
+
+-------------------------------------------------------------------------------
+-- * Kind
+
+plainTV :: Name -> TyVarBndr
+plainTV = PlainTV
+
+kindedTV :: Name -> Kind -> TyVarBndr
+kindedTV = KindedTV
+
+varK :: Name -> Kind
+varK = VarT
+
+conK :: Name -> Kind
+conK = ConT
+
+tupleK :: Int -> Kind
+tupleK = TupleT
+
+arrowK :: Kind
+arrowK = ArrowT
+
+listK :: Kind
+listK = ListT
+
+appK :: Kind -> Kind -> Kind
+appK = AppT
+
+starK :: Kind
+starK = StarT
+
+constraintK :: Kind
+constraintK = ConstraintT
+
+-------------------------------------------------------------------------------
+-- * Role
+
+nominalR, representationalR, phantomR, inferR :: Role
+nominalR = NominalR
+representationalR = RepresentationalR
+phantomR = PhantomR
+inferR = InferR
+
+-------------------------------------------------------------------------------
+-- * Callconv
+
+cCall, stdCall :: Callconv
+cCall = CCall
+stdCall = StdCall
+
+-------------------------------------------------------------------------------
+-- * Safety
+
+unsafe, safe, interruptible :: Safety
+unsafe = Unsafe
+safe = Safe
+interruptible = Interruptible
+
+-------------------------------------------------------------------------------
+-- * FunDep
+
+funDep :: [Name] -> [Name] -> FunDep
+funDep = FunDep
+
+-------------------------------------------------------------------------------
+-- * FamFlavour
+
+typeFam, dataFam :: FamFlavour
+typeFam = TypeFam
+dataFam = DataFam
+
+-------------------------------------------------------------------------------
+-- * RuleBndr
+ruleVar :: Name -> RuleBndrQ
+ruleVar = return . RuleVar
+
+typedRuleVar :: Name -> TypeQ -> RuleBndrQ
+typedRuleVar n ty = ty >>= return . TypedRuleVar n
+
+--------------------------------------------------------------
+-- * Useful helper function
+
+appsE :: [ExpQ] -> ExpQ
+appsE [] = error "appsE []"
+appsE [x] = x
+appsE (x:y:zs) = appsE ( (appE x y) : zs )
+
+-- | Return the Module at the place of splicing. Can be used as an
+-- input for 'reifyModule'.
+thisModule :: Q Module
+thisModule = do
+ loc <- location
+ return $ Module (mkPkgName $ loc_package loc) (mkModName $ loc_module loc)
diff --git a/libraries/template-haskell/Language/Haskell/TH/Lib/Map.hs b/libraries/template-haskell/Language/Haskell/TH/Lib/Map.hs
new file mode 100644
index 0000000000..ac241515b8
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/Lib/Map.hs
@@ -0,0 +1,108 @@
+{-# LANGUAGE BangPatterns #-}
+
+-- This is a non-exposed internal module
+--
+-- The code in this module has been ripped from containers-0.5.5.1:Data.Map.Base [1] almost
+-- verbatimely to avoid a dependency of 'template-haskell' on the containers package.
+--
+-- [1] see https://hackage.haskell.org/package/containers-0.5.5.1
+--
+-- The original code is BSD-licensed and copyrighted by Daan Leijen, Andriy Palamarchuk, et al.
+
+module Language.Haskell.TH.Lib.Map
+ ( Map
+ , empty
+ , insert
+ , Language.Haskell.TH.Lib.Map.lookup
+ ) where
+
+data Map k a = Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
+ | Tip
+
+type Size = Int
+
+empty :: Map k a
+empty = Tip
+{-# INLINE empty #-}
+
+singleton :: k -> a -> Map k a
+singleton k x = Bin 1 k x Tip Tip
+{-# INLINE singleton #-}
+
+size :: Map k a -> Int
+size Tip = 0
+size (Bin sz _ _ _ _) = sz
+{-# INLINE size #-}
+
+lookup :: Ord k => k -> Map k a -> Maybe a
+lookup = go
+ where
+ go _ Tip = Nothing
+ go !k (Bin _ kx x l r) = case compare k kx of
+ LT -> go k l
+ GT -> go k r
+ EQ -> Just x
+{-# INLINABLE lookup #-}
+
+
+insert :: Ord k => k -> a -> Map k a -> Map k a
+insert = go
+ where
+ go :: Ord k => k -> a -> Map k a -> Map k a
+ go !kx x Tip = singleton kx x
+ go !kx x (Bin sz ky y l r) =
+ case compare kx ky of
+ LT -> balanceL ky y (go kx x l) r
+ GT -> balanceR ky y l (go kx x r)
+ EQ -> Bin sz kx x l r
+{-# INLINABLE insert #-}
+
+balanceL :: k -> a -> Map k a -> Map k a -> Map k a
+balanceL k x l r = case r of
+ Tip -> case l of
+ Tip -> Bin 1 k x Tip Tip
+ (Bin _ _ _ Tip Tip) -> Bin 2 k x l Tip
+ (Bin _ lk lx Tip (Bin _ lrk lrx _ _)) -> Bin 3 lrk lrx (Bin 1 lk lx Tip Tip) (Bin 1 k x Tip Tip)
+ (Bin _ lk lx ll@(Bin _ _ _ _ _) Tip) -> Bin 3 lk lx ll (Bin 1 k x Tip Tip)
+ (Bin ls lk lx ll@(Bin lls _ _ _ _) lr@(Bin lrs lrk lrx lrl lrr))
+ | lrs < ratio*lls -> Bin (1+ls) lk lx ll (Bin (1+lrs) k x lr Tip)
+ | otherwise -> Bin (1+ls) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+size lrr) k x lrr Tip)
+
+ (Bin rs _ _ _ _) -> case l of
+ Tip -> Bin (1+rs) k x Tip r
+
+ (Bin ls lk lx ll lr)
+ | ls > delta*rs -> case (ll, lr) of
+ (Bin lls _ _ _ _, Bin lrs lrk lrx lrl lrr)
+ | lrs < ratio*lls -> Bin (1+ls+rs) lk lx ll (Bin (1+rs+lrs) k x lr r)
+ | otherwise -> Bin (1+ls+rs) lrk lrx (Bin (1+lls+size lrl) lk lx ll lrl) (Bin (1+rs+size lrr) k x lrr r)
+ (_, _) -> error "Failure in Data.Map.balanceL"
+ | otherwise -> Bin (1+ls+rs) k x l r
+{-# NOINLINE balanceL #-}
+
+balanceR :: k -> a -> Map k a -> Map k a -> Map k a
+balanceR k x l r = case l of
+ Tip -> case r of
+ Tip -> Bin 1 k x Tip Tip
+ (Bin _ _ _ Tip Tip) -> Bin 2 k x Tip r
+ (Bin _ rk rx Tip rr@(Bin _ _ _ _ _)) -> Bin 3 rk rx (Bin 1 k x Tip Tip) rr
+ (Bin _ rk rx (Bin _ rlk rlx _ _) Tip) -> Bin 3 rlk rlx (Bin 1 k x Tip Tip) (Bin 1 rk rx Tip Tip)
+ (Bin rs rk rx rl@(Bin rls rlk rlx rll rlr) rr@(Bin rrs _ _ _ _))
+ | rls < ratio*rrs -> Bin (1+rs) rk rx (Bin (1+rls) k x Tip rl) rr
+ | otherwise -> Bin (1+rs) rlk rlx (Bin (1+size rll) k x Tip rll) (Bin (1+rrs+size rlr) rk rx rlr rr)
+
+ (Bin ls _ _ _ _) -> case r of
+ Tip -> Bin (1+ls) k x l Tip
+
+ (Bin rs rk rx rl rr)
+ | rs > delta*ls -> case (rl, rr) of
+ (Bin rls rlk rlx rll rlr, Bin rrs _ _ _ _)
+ | rls < ratio*rrs -> Bin (1+ls+rs) rk rx (Bin (1+ls+rls) k x l rl) rr
+ | otherwise -> Bin (1+ls+rs) rlk rlx (Bin (1+ls+size rll) k x l rll) (Bin (1+rrs+size rlr) rk rx rlr rr)
+ (_, _) -> error "Failure in Data.Map.balanceR"
+ | otherwise -> Bin (1+ls+rs) k x l r
+{-# NOINLINE balanceR #-}
+
+delta,ratio :: Int
+delta = 3
+ratio = 2
diff --git a/libraries/template-haskell/Language/Haskell/TH/Ppr.hs b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
new file mode 100644
index 0000000000..e2370666e4
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/Ppr.hs
@@ -0,0 +1,568 @@
+-- | contains a prettyprinter for the
+-- Template Haskell datatypes
+
+module Language.Haskell.TH.Ppr where
+ -- All of the exports from this module should
+ -- be "public" functions. The main module TH
+ -- re-exports them all.
+
+import Text.PrettyPrint (render)
+import Language.Haskell.TH.PprLib
+import Language.Haskell.TH.Syntax
+import Data.Word ( Word8 )
+import Data.Char ( toLower, chr, ord, isSymbol )
+import GHC.Show ( showMultiLineString )
+import Data.Ratio ( numerator, denominator )
+
+nestDepth :: Int
+nestDepth = 4
+
+type Precedence = Int
+appPrec, unopPrec, opPrec, noPrec :: Precedence
+appPrec = 3 -- Argument of a function application
+opPrec = 2 -- Argument of an infix operator
+unopPrec = 1 -- Argument of an unresolved infix operator
+noPrec = 0 -- Others
+
+parensIf :: Bool -> Doc -> Doc
+parensIf True d = parens d
+parensIf False d = d
+
+------------------------------
+
+pprint :: Ppr a => a -> String
+pprint x = render $ to_HPJ_Doc $ ppr x
+
+class Ppr a where
+ ppr :: a -> Doc
+ ppr_list :: [a] -> Doc
+ ppr_list = vcat . map ppr
+
+instance Ppr a => Ppr [a] where
+ ppr x = ppr_list x
+
+------------------------------
+instance Ppr Name where
+ ppr v = pprName v
+
+------------------------------
+instance Ppr Info where
+ ppr (TyConI d) = ppr d
+ ppr (ClassI d is) = ppr d $$ vcat (map ppr is)
+ ppr (FamilyI d is) = ppr d $$ vcat (map ppr is)
+ ppr (PrimTyConI name arity is_unlifted)
+ = text "Primitive"
+ <+> (if is_unlifted then text "unlifted" else empty)
+ <+> text "type constructor" <+> quotes (ppr name)
+ <+> parens (text "arity" <+> int arity)
+ ppr (ClassOpI v ty cls fix)
+ = text "Class op from" <+> ppr cls <> colon <+>
+ vcat [ppr_sig v ty, pprFixity v fix]
+ ppr (DataConI v ty tc fix)
+ = text "Constructor from" <+> ppr tc <> colon <+>
+ vcat [ppr_sig v ty, pprFixity v fix]
+ ppr (TyVarI v ty)
+ = text "Type variable" <+> ppr v <+> equals <+> ppr ty
+ ppr (VarI v ty mb_d fix)
+ = vcat [ppr_sig v ty, pprFixity v fix,
+ case mb_d of { Nothing -> empty; Just d -> ppr d }]
+
+ppr_sig :: Name -> Type -> Doc
+ppr_sig v ty = ppr v <+> text "::" <+> ppr ty
+
+pprFixity :: Name -> Fixity -> Doc
+pprFixity _ f | f == defaultFixity = empty
+pprFixity v (Fixity i d) = ppr_fix d <+> int i <+> ppr v
+ where ppr_fix InfixR = text "infixr"
+ ppr_fix InfixL = text "infixl"
+ ppr_fix InfixN = text "infix"
+
+
+------------------------------
+instance Ppr Module where
+ ppr (Module pkg m) = text (pkgString pkg) <+> text (modString m)
+
+instance Ppr ModuleInfo where
+ ppr (ModuleInfo imps) = text "Module" <+> vcat (map ppr imps)
+
+------------------------------
+instance Ppr Exp where
+ ppr = pprExp noPrec
+
+pprPrefixOcc :: Name -> Doc
+-- Print operators with parens around them
+pprPrefixOcc n = parensIf (isSymOcc n) (ppr n)
+
+isSymOcc :: Name -> Bool
+isSymOcc n
+ = case nameBase n of
+ [] -> True -- Empty name; weird
+ (c:_) -> isSymbolASCII c || (ord c > 0x7f && isSymbol c)
+ -- c.f. OccName.startsVarSym in GHC itself
+
+isSymbolASCII :: Char -> Bool
+isSymbolASCII c = c `elem` "!#$%&*+./<=>?@\\^|~-"
+
+pprInfixExp :: Exp -> Doc
+pprInfixExp (VarE v) = pprName' Infix v
+pprInfixExp (ConE v) = pprName' Infix v
+pprInfixExp _ = text "<<Non-variable/constructor in infix context>>"
+
+pprExp :: Precedence -> Exp -> Doc
+pprExp _ (VarE v) = pprName' Applied v
+pprExp _ (ConE c) = pprName' Applied c
+pprExp i (LitE l) = pprLit i l
+pprExp i (AppE e1 e2) = parensIf (i >= appPrec) $ pprExp opPrec e1
+ <+> pprExp appPrec e2
+pprExp _ (ParensE e) = parens (pprExp noPrec e)
+pprExp i (UInfixE e1 op e2)
+ = parensIf (i > unopPrec) $ pprExp unopPrec e1
+ <+> pprInfixExp op
+ <+> pprExp unopPrec e2
+pprExp i (InfixE (Just e1) op (Just e2))
+ = parensIf (i >= opPrec) $ pprExp opPrec e1
+ <+> pprInfixExp op
+ <+> pprExp opPrec e2
+pprExp _ (InfixE me1 op me2) = parens $ pprMaybeExp noPrec me1
+ <+> pprInfixExp op
+ <+> pprMaybeExp noPrec me2
+pprExp i (LamE ps e) = parensIf (i > noPrec) $ char '\\' <> hsep (map (pprPat appPrec) ps)
+ <+> text "->" <+> ppr e
+pprExp i (LamCaseE ms) = parensIf (i > noPrec)
+ $ text "\\case" $$ nest nestDepth (ppr ms)
+pprExp _ (TupE es) = parens $ sep $ punctuate comma $ map ppr es
+pprExp _ (UnboxedTupE es) = hashParens $ sep $ punctuate comma $ map ppr es
+-- Nesting in Cond is to avoid potential problems in do statments
+pprExp i (CondE guard true false)
+ = parensIf (i > noPrec) $ sep [text "if" <+> ppr guard,
+ nest 1 $ text "then" <+> ppr true,
+ nest 1 $ text "else" <+> ppr false]
+pprExp i (MultiIfE alts)
+ = parensIf (i > noPrec) $ vcat $
+ case alts of
+ [] -> [text "if {}"]
+ (alt : alts') -> text "if" <+> pprGuarded arrow alt
+ : map (nest 3 . pprGuarded arrow) alts'
+pprExp i (LetE ds_ e) = parensIf (i > noPrec) $ text "let" <+> pprDecs ds_
+ $$ text " in" <+> ppr e
+ where
+ pprDecs [] = empty
+ pprDecs [d] = ppr d
+ pprDecs ds = braces $ sep $ punctuate semi $ map ppr ds
+
+pprExp i (CaseE e ms)
+ = parensIf (i > noPrec) $ text "case" <+> ppr e <+> text "of"
+ $$ nest nestDepth (ppr ms)
+pprExp i (DoE ss_) = parensIf (i > noPrec) $ text "do" <+> pprStms ss_
+ where
+ pprStms [] = empty
+ pprStms [s] = ppr s
+ pprStms ss = braces $ sep $ punctuate semi $ map ppr ss
+
+pprExp _ (CompE []) = text "<<Empty CompExp>>"
+-- This will probably break with fixity declarations - would need a ';'
+pprExp _ (CompE ss) = text "[" <> ppr s
+ <+> text "|"
+ <+> (sep $ punctuate comma $ map ppr ss')
+ <> text "]"
+ where s = last ss
+ ss' = init ss
+pprExp _ (ArithSeqE d) = ppr d
+pprExp _ (ListE es) = brackets $ sep $ punctuate comma $ map ppr es
+pprExp i (SigE e t) = parensIf (i > noPrec) $ ppr e <+> text "::" <+> ppr t
+pprExp _ (RecConE nm fs) = ppr nm <> braces (pprFields fs)
+pprExp _ (RecUpdE e fs) = pprExp appPrec e <> braces (pprFields fs)
+
+pprFields :: [(Name,Exp)] -> Doc
+pprFields = sep . punctuate comma . map (\(s,e) -> ppr s <+> equals <+> ppr e)
+
+pprMaybeExp :: Precedence -> Maybe Exp -> Doc
+pprMaybeExp _ Nothing = empty
+pprMaybeExp i (Just e) = pprExp i e
+
+------------------------------
+instance Ppr Stmt where
+ ppr (BindS p e) = ppr p <+> text "<-" <+> ppr e
+ ppr (LetS ds) = text "let" <+> ppr ds
+ ppr (NoBindS e) = ppr e
+ ppr (ParS sss) = sep $ punctuate (text "|")
+ $ map (sep . punctuate comma . map ppr) sss
+
+------------------------------
+instance Ppr Match where
+ ppr (Match p rhs ds) = ppr p <+> pprBody False rhs
+ $$ where_clause ds
+
+------------------------------
+pprGuarded :: Doc -> (Guard, Exp) -> Doc
+pprGuarded eqDoc (guard, expr) = case guard of
+ NormalG guardExpr -> char '|' <+> ppr guardExpr <+> eqDoc <+> ppr expr
+ PatG stmts -> char '|' <+> vcat (punctuate comma $ map ppr stmts) $$
+ nest nestDepth (eqDoc <+> ppr expr)
+
+------------------------------
+pprBody :: Bool -> Body -> Doc
+pprBody eq body = case body of
+ GuardedB xs -> nest nestDepth $ vcat $ map (pprGuarded eqDoc) xs
+ NormalB e -> eqDoc <+> ppr e
+ where eqDoc | eq = equals
+ | otherwise = arrow
+
+------------------------------
+pprLit :: Precedence -> Lit -> Doc
+pprLit i (IntPrimL x) = parensIf (i > noPrec && x < 0)
+ (integer x <> char '#')
+pprLit _ (WordPrimL x) = integer x <> text "##"
+pprLit i (FloatPrimL x) = parensIf (i > noPrec && x < 0)
+ (float (fromRational x) <> char '#')
+pprLit i (DoublePrimL x) = parensIf (i > noPrec && x < 0)
+ (double (fromRational x) <> text "##")
+pprLit i (IntegerL x) = parensIf (i > noPrec && x < 0) (integer x)
+pprLit _ (CharL c) = text (show c)
+pprLit _ (StringL s) = pprString s
+pprLit _ (StringPrimL s) = pprString (bytesToString s) <> char '#'
+pprLit i (RationalL rat) = parensIf (i > noPrec) $
+ integer (numerator rat) <+> char '/'
+ <+> integer (denominator rat)
+
+bytesToString :: [Word8] -> String
+bytesToString = map (chr . fromIntegral)
+
+pprString :: String -> Doc
+-- Print newlines as newlines with Haskell string escape notation,
+-- not as '\n'. For other non-printables use regular escape notation.
+pprString s = vcat (map text (showMultiLineString s))
+
+------------------------------
+instance Ppr Pat where
+ ppr = pprPat noPrec
+
+pprPat :: Precedence -> Pat -> Doc
+pprPat i (LitP l) = pprLit i l
+pprPat _ (VarP v) = pprName' Applied v
+pprPat _ (TupP ps) = parens $ sep $ punctuate comma $ map ppr ps
+pprPat _ (UnboxedTupP ps) = hashParens $ sep $ punctuate comma $ map ppr ps
+pprPat i (ConP s ps) = parensIf (i >= appPrec) $ pprName' Applied s
+ <+> sep (map (pprPat appPrec) ps)
+pprPat _ (ParensP p) = parens $ pprPat noPrec p
+pprPat i (UInfixP p1 n p2)
+ = parensIf (i > unopPrec) (pprPat unopPrec p1 <+>
+ pprName' Infix n <+>
+ pprPat unopPrec p2)
+pprPat i (InfixP p1 n p2)
+ = parensIf (i >= opPrec) (pprPat opPrec p1 <+>
+ pprName' Infix n <+>
+ pprPat opPrec p2)
+pprPat i (TildeP p) = parensIf (i > noPrec) $ char '~' <> pprPat appPrec p
+pprPat i (BangP p) = parensIf (i > noPrec) $ char '!' <> pprPat appPrec p
+pprPat i (AsP v p) = parensIf (i > noPrec) $ ppr v <> text "@"
+ <> pprPat appPrec p
+pprPat _ WildP = text "_"
+pprPat _ (RecP nm fs)
+ = parens $ ppr nm
+ <+> braces (sep $ punctuate comma $
+ map (\(s,p) -> ppr s <+> equals <+> ppr p) fs)
+pprPat _ (ListP ps) = brackets $ sep $ punctuate comma $ map ppr ps
+pprPat i (SigP p t) = parensIf (i > noPrec) $ ppr p <+> text "::" <+> ppr t
+pprPat _ (ViewP e p) = parens $ pprExp noPrec e <+> text "->" <+> pprPat noPrec p
+
+------------------------------
+instance Ppr Dec where
+ ppr = ppr_dec True
+
+ppr_dec :: Bool -- declaration on the toplevel?
+ -> Dec
+ -> Doc
+ppr_dec _ (FunD f cs) = vcat $ map (\c -> pprPrefixOcc f <+> ppr c) cs
+ppr_dec _ (ValD p r ds) = ppr p <+> pprBody True r
+ $$ where_clause ds
+ppr_dec _ (TySynD t xs rhs)
+ = ppr_tySyn empty t (hsep (map ppr xs)) rhs
+ppr_dec _ (DataD ctxt t xs cs decs)
+ = ppr_data empty ctxt t (hsep (map ppr xs)) cs decs
+ppr_dec _ (NewtypeD ctxt t xs c decs)
+ = ppr_newtype empty ctxt t (sep (map ppr xs)) c decs
+ppr_dec _ (ClassD ctxt c xs fds ds)
+ = text "class" <+> pprCxt ctxt <+> ppr c <+> hsep (map ppr xs) <+> ppr fds
+ $$ where_clause ds
+ppr_dec _ (InstanceD ctxt i ds) = text "instance" <+> pprCxt ctxt <+> ppr i
+ $$ where_clause ds
+ppr_dec _ (SigD f t) = pprPrefixOcc f <+> text "::" <+> ppr t
+ppr_dec _ (ForeignD f) = ppr f
+ppr_dec _ (InfixD fx n) = pprFixity n fx
+ppr_dec _ (PragmaD p) = ppr p
+ppr_dec isTop (FamilyD flav tc tvs k)
+ = ppr flav <+> maybeFamily <+> ppr tc <+> hsep (map ppr tvs) <+> maybeKind
+ where
+ maybeFamily | isTop = text "family"
+ | otherwise = empty
+
+ maybeKind | (Just k') <- k = text "::" <+> ppr k'
+ | otherwise = empty
+ppr_dec isTop (DataInstD ctxt tc tys cs decs)
+ = ppr_data maybeInst ctxt tc (sep (map pprParendType tys)) cs decs
+ where
+ maybeInst | isTop = text "instance"
+ | otherwise = empty
+ppr_dec isTop (NewtypeInstD ctxt tc tys c decs)
+ = ppr_newtype maybeInst ctxt tc (sep (map pprParendType tys)) c decs
+ where
+ maybeInst | isTop = text "instance"
+ | otherwise = empty
+ppr_dec isTop (TySynInstD tc (TySynEqn tys rhs))
+ = ppr_tySyn maybeInst tc (sep (map pprParendType tys)) rhs
+ where
+ maybeInst | isTop = text "instance"
+ | otherwise = empty
+ppr_dec _ (ClosedTypeFamilyD tc tvs mkind eqns)
+ = hang (hsep [ text "type family", ppr tc, hsep (map ppr tvs), maybeKind
+ , text "where" ])
+ nestDepth (vcat (map ppr_eqn eqns))
+ where
+ maybeKind | (Just k') <- mkind = text "::" <+> ppr k'
+ | otherwise = empty
+ ppr_eqn (TySynEqn lhs rhs)
+ = ppr tc <+> sep (map pprParendType lhs) <+> text "=" <+> ppr rhs
+
+ppr_dec _ (RoleAnnotD name roles)
+ = hsep [ text "type role", ppr name ] <+> hsep (map ppr roles)
+
+ppr_data :: Doc -> Cxt -> Name -> Doc -> [Con] -> [Name] -> Doc
+ppr_data maybeInst ctxt t argsDoc cs decs
+ = sep [text "data" <+> maybeInst
+ <+> pprCxt ctxt
+ <+> ppr t <+> argsDoc,
+ nest nestDepth (sep (pref $ map ppr cs)),
+ if null decs
+ then empty
+ else nest nestDepth
+ $ text "deriving"
+ <+> parens (hsep $ punctuate comma $ map ppr decs)]
+ where
+ pref :: [Doc] -> [Doc]
+ pref [] = [] -- No constructors; can't happen in H98
+ pref (d:ds) = (char '=' <+> d):map (char '|' <+>) ds
+
+ppr_newtype :: Doc -> Cxt -> Name -> Doc -> Con -> [Name] -> Doc
+ppr_newtype maybeInst ctxt t argsDoc c decs
+ = sep [text "newtype" <+> maybeInst
+ <+> pprCxt ctxt
+ <+> ppr t <+> argsDoc,
+ nest 2 (char '=' <+> ppr c),
+ if null decs
+ then empty
+ else nest nestDepth
+ $ text "deriving"
+ <+> parens (hsep $ punctuate comma $ map ppr decs)]
+
+ppr_tySyn :: Doc -> Name -> Doc -> Type -> Doc
+ppr_tySyn maybeInst t argsDoc rhs
+ = text "type" <+> maybeInst <+> ppr t <+> argsDoc <+> text "=" <+> ppr rhs
+
+------------------------------
+instance Ppr FunDep where
+ ppr (FunDep xs ys) = hsep (map ppr xs) <+> text "->" <+> hsep (map ppr ys)
+ ppr_list [] = empty
+ ppr_list xs = char '|' <+> sep (punctuate (text ", ") (map ppr xs))
+
+------------------------------
+instance Ppr FamFlavour where
+ ppr DataFam = text "data"
+ ppr TypeFam = text "type"
+
+------------------------------
+instance Ppr Foreign where
+ ppr (ImportF callconv safety impent as typ)
+ = text "foreign import"
+ <+> showtextl callconv
+ <+> showtextl safety
+ <+> text (show impent)
+ <+> ppr as
+ <+> text "::" <+> ppr typ
+ ppr (ExportF callconv expent as typ)
+ = text "foreign export"
+ <+> showtextl callconv
+ <+> text (show expent)
+ <+> ppr as
+ <+> text "::" <+> ppr typ
+
+------------------------------
+instance Ppr Pragma where
+ ppr (InlineP n inline rm phases)
+ = text "{-#"
+ <+> ppr inline
+ <+> ppr rm
+ <+> ppr phases
+ <+> ppr n
+ <+> text "#-}"
+ ppr (SpecialiseP n ty inline phases)
+ = text "{-# SPECIALISE"
+ <+> maybe empty ppr inline
+ <+> ppr phases
+ <+> sep [ ppr n <+> text "::"
+ , nest 2 $ ppr ty ]
+ <+> text "#-}"
+ ppr (SpecialiseInstP inst)
+ = text "{-# SPECIALISE instance" <+> ppr inst <+> text "#-}"
+ ppr (RuleP n bndrs lhs rhs phases)
+ = sep [ text "{-# RULES" <+> pprString n <+> ppr phases
+ , nest 4 $ ppr_forall <+> ppr lhs
+ , nest 4 $ char '=' <+> ppr rhs <+> text "#-}" ]
+ where ppr_forall | null bndrs = empty
+ | otherwise = text "forall"
+ <+> fsep (map ppr bndrs)
+ <+> char '.'
+ ppr (AnnP tgt expr)
+ = text "{-# ANN" <+> target1 tgt <+> ppr expr <+> text "#-}"
+ where target1 ModuleAnnotation = text "module"
+ target1 (TypeAnnotation t) = text "type" <+> ppr t
+ target1 (ValueAnnotation v) = ppr v
+
+------------------------------
+instance Ppr Inline where
+ ppr NoInline = text "NOINLINE"
+ ppr Inline = text "INLINE"
+ ppr Inlinable = text "INLINABLE"
+
+------------------------------
+instance Ppr RuleMatch where
+ ppr ConLike = text "CONLIKE"
+ ppr FunLike = empty
+
+------------------------------
+instance Ppr Phases where
+ ppr AllPhases = empty
+ ppr (FromPhase i) = brackets $ int i
+ ppr (BeforePhase i) = brackets $ char '~' <> int i
+
+------------------------------
+instance Ppr RuleBndr where
+ ppr (RuleVar n) = ppr n
+ ppr (TypedRuleVar n ty) = parens $ ppr n <+> text "::" <+> ppr ty
+
+------------------------------
+instance Ppr Clause where
+ ppr (Clause ps rhs ds) = hsep (map (pprPat appPrec) ps) <+> pprBody True rhs
+ $$ where_clause ds
+
+------------------------------
+instance Ppr Con where
+ ppr (NormalC c sts) = ppr c <+> sep (map pprStrictType sts)
+ ppr (RecC c vsts)
+ = ppr c <+> braces (sep (punctuate comma $ map pprVarStrictType vsts))
+ ppr (InfixC st1 c st2) = pprStrictType st1
+ <+> pprName' Infix c
+ <+> pprStrictType st2
+ ppr (ForallC ns ctxt con) = text "forall" <+> hsep (map ppr ns)
+ <+> char '.' <+> sep [pprCxt ctxt, ppr con]
+
+------------------------------
+pprVarStrictType :: (Name, Strict, Type) -> Doc
+-- Slight infelicity: with print non-atomic type with parens
+pprVarStrictType (v, str, t) = ppr v <+> text "::" <+> pprStrictType (str, t)
+
+------------------------------
+pprStrictType :: (Strict, Type) -> Doc
+-- Prints with parens if not already atomic
+pprStrictType (IsStrict, t) = char '!' <> pprParendType t
+pprStrictType (NotStrict, t) = pprParendType t
+pprStrictType (Unpacked, t) = text "{-# UNPACK #-} !" <> pprParendType t
+
+------------------------------
+pprParendType :: Type -> Doc
+pprParendType (VarT v) = ppr v
+pprParendType (ConT c) = ppr c
+pprParendType (TupleT 0) = text "()"
+pprParendType (TupleT n) = parens (hcat (replicate (n-1) comma))
+pprParendType (UnboxedTupleT n) = hashParens $ hcat $ replicate (n-1) comma
+pprParendType ArrowT = parens (text "->")
+pprParendType ListT = text "[]"
+pprParendType (LitT l) = pprTyLit l
+pprParendType (PromotedT c) = text "'" <> ppr c
+pprParendType (PromotedTupleT 0) = text "'()"
+pprParendType (PromotedTupleT n) = quoteParens (hcat (replicate (n-1) comma))
+pprParendType PromotedNilT = text "'[]"
+pprParendType PromotedConsT = text "(':)"
+pprParendType StarT = char '*'
+pprParendType ConstraintT = text "Constraint"
+pprParendType other = parens (ppr other)
+
+instance Ppr Type where
+ ppr (ForallT tvars ctxt ty)
+ = text "forall" <+> hsep (map ppr tvars) <+> text "."
+ <+> sep [pprCxt ctxt, ppr ty]
+ ppr (SigT ty k) = ppr ty <+> text "::" <+> ppr k
+ ppr ty = pprTyApp (split ty)
+
+pprTyApp :: (Type, [Type]) -> Doc
+pprTyApp (ArrowT, [arg1,arg2]) = sep [pprFunArgType arg1 <+> text "->", ppr arg2]
+pprTyApp (EqualityT, [arg1, arg2]) =
+ sep [pprFunArgType arg1 <+> text "~", ppr arg2]
+pprTyApp (ListT, [arg]) = brackets (ppr arg)
+pprTyApp (TupleT n, args)
+ | length args == n = parens (sep (punctuate comma (map ppr args)))
+pprTyApp (PromotedTupleT n, args)
+ | length args == n = quoteParens (sep (punctuate comma (map ppr args)))
+pprTyApp (fun, args) = pprParendType fun <+> sep (map pprParendType args)
+
+pprFunArgType :: Type -> Doc -- Should really use a precedence argument
+-- Everything except forall and (->) binds more tightly than (->)
+pprFunArgType ty@(ForallT {}) = parens (ppr ty)
+pprFunArgType ty@((ArrowT `AppT` _) `AppT` _) = parens (ppr ty)
+pprFunArgType ty@(SigT _ _) = parens (ppr ty)
+pprFunArgType ty = ppr ty
+
+split :: Type -> (Type, [Type]) -- Split into function and args
+split t = go t []
+ where go (AppT t1 t2) args = go t1 (t2:args)
+ go ty args = (ty, args)
+
+pprTyLit :: TyLit -> Doc
+pprTyLit (NumTyLit n) = integer n
+pprTyLit (StrTyLit s) = text (show s)
+
+instance Ppr TyLit where
+ ppr = pprTyLit
+
+------------------------------
+instance Ppr TyVarBndr where
+ ppr (PlainTV nm) = ppr nm
+ ppr (KindedTV nm k) = parens (ppr nm <+> text "::" <+> ppr k)
+
+instance Ppr Role where
+ ppr NominalR = text "nominal"
+ ppr RepresentationalR = text "representational"
+ ppr PhantomR = text "phantom"
+ ppr InferR = text "_"
+
+------------------------------
+pprCxt :: Cxt -> Doc
+pprCxt [] = empty
+pprCxt [t] = ppr t <+> text "=>"
+pprCxt ts = parens (sep $ punctuate comma $ map ppr ts) <+> text "=>"
+
+------------------------------
+instance Ppr Range where
+ ppr = brackets . pprRange
+ where pprRange :: Range -> Doc
+ pprRange (FromR e) = ppr e <> text ".."
+ pprRange (FromThenR e1 e2) = ppr e1 <> text ","
+ <> ppr e2 <> text ".."
+ pprRange (FromToR e1 e2) = ppr e1 <> text ".." <> ppr e2
+ pprRange (FromThenToR e1 e2 e3) = ppr e1 <> text ","
+ <> ppr e2 <> text ".."
+ <> ppr e3
+
+------------------------------
+where_clause :: [Dec] -> Doc
+where_clause [] = empty
+where_clause ds = nest nestDepth $ text "where" <+> vcat (map (ppr_dec False) ds)
+
+showtextl :: Show a => a -> Doc
+showtextl = text . map toLower . show
+
+hashParens :: Doc -> Doc
+hashParens d = text "(# " <> d <> text " #)"
+
+quoteParens :: Doc -> Doc
+quoteParens d = text "'(" <> d <> text ")"
diff --git a/libraries/template-haskell/Language/Haskell/TH/PprLib.hs b/libraries/template-haskell/Language/Haskell/TH/PprLib.hs
new file mode 100644
index 0000000000..c4b0b77430
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/PprLib.hs
@@ -0,0 +1,227 @@
+{-# LANGUAGE FlexibleInstances, MagicHash #-}
+
+-- | Monadic front-end to Text.PrettyPrint
+
+module Language.Haskell.TH.PprLib (
+
+ -- * The document type
+ Doc, -- Abstract, instance of Show
+ PprM,
+
+ -- * Primitive Documents
+ empty,
+ semi, comma, colon, space, equals, arrow,
+ lparen, rparen, lbrack, rbrack, lbrace, rbrace,
+
+ -- * Converting values into documents
+ text, char, ptext,
+ int, integer, float, double, rational,
+
+ -- * Wrapping documents in delimiters
+ parens, brackets, braces, quotes, doubleQuotes,
+
+ -- * Combining documents
+ (<>), (<+>), hcat, hsep,
+ ($$), ($+$), vcat,
+ sep, cat,
+ fsep, fcat,
+ nest,
+ hang, punctuate,
+
+ -- * Predicates on documents
+ isEmpty,
+
+ to_HPJ_Doc, pprName, pprName'
+ ) where
+
+
+import Language.Haskell.TH.Syntax
+ (Name(..), showName', NameFlavour(..), NameIs(..))
+import qualified Text.PrettyPrint as HPJ
+import Control.Applicative (Applicative(..))
+import Control.Monad (liftM, liftM2, ap)
+import Language.Haskell.TH.Lib.Map ( Map )
+import qualified Language.Haskell.TH.Lib.Map as Map ( lookup, insert, empty )
+import GHC.Base (Int(..))
+
+infixl 6 <>
+infixl 6 <+>
+infixl 5 $$, $+$
+
+-- ---------------------------------------------------------------------------
+-- The interface
+
+-- The primitive Doc values
+
+instance Show Doc where
+ show d = HPJ.render (to_HPJ_Doc d)
+
+isEmpty :: Doc -> PprM Bool; -- ^ Returns 'True' if the document is empty
+
+empty :: Doc; -- ^ An empty document
+semi :: Doc; -- ^ A ';' character
+comma :: Doc; -- ^ A ',' character
+colon :: Doc; -- ^ A ':' character
+space :: Doc; -- ^ A space character
+equals :: Doc; -- ^ A '=' character
+arrow :: Doc; -- ^ A "->" string
+lparen :: Doc; -- ^ A '(' character
+rparen :: Doc; -- ^ A ')' character
+lbrack :: Doc; -- ^ A '[' character
+rbrack :: Doc; -- ^ A ']' character
+lbrace :: Doc; -- ^ A '{' character
+rbrace :: Doc; -- ^ A '}' character
+
+text :: String -> Doc
+ptext :: String -> Doc
+char :: Char -> Doc
+int :: Int -> Doc
+integer :: Integer -> Doc
+float :: Float -> Doc
+double :: Double -> Doc
+rational :: Rational -> Doc
+
+
+parens :: Doc -> Doc; -- ^ Wrap document in @(...)@
+brackets :: Doc -> Doc; -- ^ Wrap document in @[...]@
+braces :: Doc -> Doc; -- ^ Wrap document in @{...}@
+quotes :: Doc -> Doc; -- ^ Wrap document in @\'...\'@
+doubleQuotes :: Doc -> Doc; -- ^ Wrap document in @\"...\"@
+
+-- Combining @Doc@ values
+
+(<>) :: Doc -> Doc -> Doc; -- ^Beside
+hcat :: [Doc] -> Doc; -- ^List version of '<>'
+(<+>) :: Doc -> Doc -> Doc; -- ^Beside, separated by space
+hsep :: [Doc] -> Doc; -- ^List version of '<+>'
+
+($$) :: Doc -> Doc -> Doc; -- ^Above; if there is no
+ -- overlap it \"dovetails\" the two
+($+$) :: Doc -> Doc -> Doc; -- ^Above, without dovetailing.
+vcat :: [Doc] -> Doc; -- ^List version of '$$'
+
+cat :: [Doc] -> Doc; -- ^ Either hcat or vcat
+sep :: [Doc] -> Doc; -- ^ Either hsep or vcat
+fcat :: [Doc] -> Doc; -- ^ \"Paragraph fill\" version of cat
+fsep :: [Doc] -> Doc; -- ^ \"Paragraph fill\" version of sep
+
+nest :: Int -> Doc -> Doc; -- ^ Nested
+
+
+-- GHC-specific ones.
+
+hang :: Doc -> Int -> Doc -> Doc; -- ^ @hang d1 n d2 = sep [d1, nest n d2]@
+punctuate :: Doc -> [Doc] -> [Doc]; -- ^ @punctuate p [d1, ... dn] = [d1 \<> p, d2 \<> p, ... dn-1 \<> p, dn]@
+
+
+-- ---------------------------------------------------------------------------
+-- The "implementation"
+
+type State = (Map Name Name, Int)
+data PprM a = PprM { runPprM :: State -> (a, State) }
+
+pprName :: Name -> Doc
+pprName = pprName' Alone
+
+pprName' :: NameIs -> Name -> Doc
+pprName' ni n@(Name o (NameU _))
+ = PprM $ \s@(fm, i@(I# i'))
+ -> let (n', s') = case Map.lookup n fm of
+ Just d -> (d, s)
+ Nothing -> let n'' = Name o (NameU i')
+ in (n'', (Map.insert n n'' fm, i + 1))
+ in (HPJ.text $ showName' ni n', s')
+pprName' ni n = text $ showName' ni n
+
+{-
+instance Show Name where
+ show (Name occ (NameU u)) = occString occ ++ "_" ++ show (I# u)
+ show (Name occ NameS) = occString occ
+ show (Name occ (NameG ns m)) = modString m ++ "." ++ occString occ
+
+data Name = Name OccName NameFlavour
+
+data NameFlavour
+ | NameU Int# -- A unique local name
+-}
+
+to_HPJ_Doc :: Doc -> HPJ.Doc
+to_HPJ_Doc d = fst $ runPprM d (Map.empty, 0)
+
+instance Functor PprM where
+ fmap = liftM
+
+instance Applicative PprM where
+ pure = return
+ (<*>) = ap
+
+instance Monad PprM where
+ return x = PprM $ \s -> (x, s)
+ m >>= k = PprM $ \s -> let (x, s') = runPprM m s
+ in runPprM (k x) s'
+
+type Doc = PprM HPJ.Doc
+
+-- The primitive Doc values
+
+isEmpty = liftM HPJ.isEmpty
+
+empty = return HPJ.empty
+semi = return HPJ.semi
+comma = return HPJ.comma
+colon = return HPJ.colon
+space = return HPJ.space
+equals = return HPJ.equals
+arrow = return $ HPJ.text "->"
+lparen = return HPJ.lparen
+rparen = return HPJ.rparen
+lbrack = return HPJ.lbrack
+rbrack = return HPJ.rbrack
+lbrace = return HPJ.lbrace
+rbrace = return HPJ.rbrace
+
+text = return . HPJ.text
+ptext = return . HPJ.ptext
+char = return . HPJ.char
+int = return . HPJ.int
+integer = return . HPJ.integer
+float = return . HPJ.float
+double = return . HPJ.double
+rational = return . HPJ.rational
+
+
+parens = liftM HPJ.parens
+brackets = liftM HPJ.brackets
+braces = liftM HPJ.braces
+quotes = liftM HPJ.quotes
+doubleQuotes = liftM HPJ.doubleQuotes
+
+-- Combining @Doc@ values
+
+(<>) = liftM2 (HPJ.<>)
+hcat = liftM HPJ.hcat . sequence
+(<+>) = liftM2 (HPJ.<+>)
+hsep = liftM HPJ.hsep . sequence
+
+($$) = liftM2 (HPJ.$$)
+($+$) = liftM2 (HPJ.$+$)
+vcat = liftM HPJ.vcat . sequence
+
+cat = liftM HPJ.cat . sequence
+sep = liftM HPJ.sep . sequence
+fcat = liftM HPJ.fcat . sequence
+fsep = liftM HPJ.fsep . sequence
+
+nest n = liftM (HPJ.nest n)
+
+hang d1 n d2 = do d1' <- d1
+ d2' <- d2
+ return (HPJ.hang d1' n d2')
+
+-- punctuate uses the same definition as Text.PrettyPrint
+punctuate _ [] = []
+punctuate p (d:ds) = go d ds
+ where
+ go d' [] = [d']
+ go d' (e:es) = (d' <> p) : go e es
+
diff --git a/libraries/template-haskell/Language/Haskell/TH/Quote.hs b/libraries/template-haskell/Language/Haskell/TH/Quote.hs
new file mode 100644
index 0000000000..b9c0d25d2b
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/Quote.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
+module Language.Haskell.TH.Quote(
+ QuasiQuoter(..),
+ dataToQa, dataToExpQ, dataToPatQ,
+ quoteFile
+ ) where
+
+import Data.Data
+import Language.Haskell.TH.Lib
+import Language.Haskell.TH.Syntax
+
+data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp,
+ quotePat :: String -> Q Pat,
+ quoteType :: String -> Q Type,
+ quoteDec :: String -> Q [Dec] }
+
+dataToQa :: forall a k q. Data a
+ => (Name -> k)
+ -> (Lit -> Q q)
+ -> (k -> [Q q] -> Q q)
+ -> (forall b . Data b => b -> Maybe (Q q))
+ -> a
+ -> Q q
+dataToQa mkCon mkLit appCon antiQ t =
+ case antiQ t of
+ Nothing ->
+ case constrRep constr of
+ AlgConstr _ ->
+ appCon (mkCon conName) conArgs
+ where
+ conName :: Name
+ conName =
+ case showConstr constr of
+ "(:)" -> Name (mkOccName ":") (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Types"))
+ con@"[]" -> Name (mkOccName con) (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Types"))
+ con@('(':_) -> Name (mkOccName con) (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Tuple"))
+ con -> mkNameG_d (tyConPackage tycon)
+ (tyConModule tycon)
+ con
+ where
+ tycon :: TyCon
+ tycon = (typeRepTyCon . typeOf) t
+
+ conArgs :: [Q q]
+ conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
+ IntConstr n ->
+ mkLit $ integerL n
+ FloatConstr n ->
+ mkLit $ rationalL n
+ CharConstr c ->
+ mkLit $ charL c
+ where
+ constr :: Constr
+ constr = toConstr t
+
+ Just y -> y
+
+-- | 'dataToExpQ' converts a value to a 'Q Exp' representation of the same
+-- value. It takes a function to handle type-specific cases.
+dataToExpQ :: Data a
+ => (forall b . Data b => b -> Maybe (Q Exp))
+ -> a
+ -> Q Exp
+dataToExpQ = dataToQa conE litE (foldl appE)
+
+-- | 'dataToPatQ' converts a value to a 'Q Pat' representation of the same
+-- value. It takes a function to handle type-specific cases.
+dataToPatQ :: Data a
+ => (forall b . Data b => b -> Maybe (Q Pat))
+ -> a
+ -> Q Pat
+dataToPatQ = dataToQa id litP conP
+
+-- | 'quoteFile' takes a 'QuasiQuoter' and lifts it into one that read
+-- the data out of a file. For example, suppose 'asmq' is an
+-- assembly-language quoter, so that you can write [asmq| ld r1, r2 |]
+-- as an expression. Then if you define @asmq_f = quoteFile asmq@, then
+-- the quote [asmq_f|foo.s|] will take input from file @"foo.s"@ instead
+-- of the inline text
+quoteFile :: QuasiQuoter -> QuasiQuoter
+quoteFile (QuasiQuoter { quoteExp = qe, quotePat = qp, quoteType = qt, quoteDec = qd })
+ = QuasiQuoter { quoteExp = get qe, quotePat = get qp, quoteType = get qt, quoteDec = get qd }
+ where
+ get :: (String -> Q a) -> String -> Q a
+ get old_quoter file_name = do { file_cts <- runIO (readFile file_name)
+ ; addDependentFile file_name
+ ; old_quoter file_cts }
diff --git a/libraries/template-haskell/Language/Haskell/TH/Syntax.hs b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
new file mode 100644
index 0000000000..3172cbbced
--- /dev/null
+++ b/libraries/template-haskell/Language/Haskell/TH/Syntax.hs
@@ -0,0 +1,1457 @@
+{-# LANGUAGE DeriveDataTypeable, MagicHash, PolymorphicComponents, RoleAnnotations, UnboxedTuples #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module : Language.Haskell.Syntax
+-- Copyright : (c) The University of Glasgow 2003
+-- License : BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer : libraries@haskell.org
+-- Stability : experimental
+-- Portability : portable
+--
+-- Abstract syntax definitions for Template Haskell.
+--
+-----------------------------------------------------------------------------
+
+module Language.Haskell.TH.Syntax where
+
+import GHC.Exts
+import Data.Data (Data(..), Typeable, mkConstr, mkDataType, constrIndex)
+import qualified Data.Data as Data
+import Control.Applicative( Applicative(..) )
+import Data.IORef
+import System.IO.Unsafe ( unsafePerformIO )
+import Control.Monad (liftM)
+import System.IO ( hPutStrLn, stderr )
+import Data.Char ( isAlpha, isAlphaNum, isUpper )
+import Data.Word ( Word8 )
+
+-----------------------------------------------------
+--
+-- The Quasi class
+--
+-----------------------------------------------------
+
+class (Monad m, Applicative m) => Quasi m where
+ qNewName :: String -> m Name
+ -- ^ Fresh names
+
+ -- Error reporting and recovery
+ qReport :: Bool -> String -> m () -- ^ Report an error (True) or warning (False)
+ -- ...but carry on; use 'fail' to stop
+ qRecover :: m a -- ^ the error handler
+ -> m a -- ^ action which may fail
+ -> m a -- ^ Recover from the monadic 'fail'
+
+ -- Inspect the type-checker's environment
+ qLookupName :: Bool -> String -> m (Maybe Name)
+ -- True <=> type namespace, False <=> value namespace
+ qReify :: Name -> m Info
+ qReifyInstances :: Name -> [Type] -> m [Dec]
+ -- Is (n tys) an instance?
+ -- Returns list of matching instance Decs
+ -- (with empty sub-Decs)
+ -- Works for classes and type functions
+ qReifyRoles :: Name -> m [Role]
+ qReifyAnnotations :: Data a => AnnLookup -> m [a]
+ qReifyModule :: Module -> m ModuleInfo
+
+ qLocation :: m Loc
+
+ qRunIO :: IO a -> m a
+ -- ^ Input/output (dangerous)
+
+ qAddDependentFile :: FilePath -> m ()
+
+ qAddTopDecls :: [Dec] -> m ()
+
+ qAddModFinalizer :: Q () -> m ()
+
+ qGetQ :: Typeable a => m (Maybe a)
+
+ qPutQ :: Typeable a => a -> m ()
+
+-----------------------------------------------------
+-- The IO instance of Quasi
+--
+-- This instance is used only when running a Q
+-- computation in the IO monad, usually just to
+-- print the result. There is no interesting
+-- type environment, so reification isn't going to
+-- work.
+--
+-----------------------------------------------------
+
+instance Quasi IO where
+ qNewName s = do { n <- readIORef counter
+ ; writeIORef counter (n+1)
+ ; return (mkNameU s n) }
+
+ qReport True msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
+ qReport False msg = hPutStrLn stderr ("Template Haskell error: " ++ msg)
+
+ qLookupName _ _ = badIO "lookupName"
+ qReify _ = badIO "reify"
+ qReifyInstances _ _ = badIO "reifyInstances"
+ qReifyRoles _ = badIO "reifyRoles"
+ qReifyAnnotations _ = badIO "reifyAnnotations"
+ qReifyModule _ = badIO "reifyModule"
+ qLocation = badIO "currentLocation"
+ qRecover _ _ = badIO "recover" -- Maybe we could fix this?
+ qAddDependentFile _ = badIO "addDependentFile"
+ qAddTopDecls _ = badIO "addTopDecls"
+ qAddModFinalizer _ = badIO "addModFinalizer"
+ qGetQ = badIO "getQ"
+ qPutQ _ = badIO "putQ"
+
+ qRunIO m = m
+
+badIO :: String -> IO a
+badIO op = do { qReport True ("Can't do `" ++ op ++ "' in the IO monad")
+ ; fail "Template Haskell failure" }
+
+-- Global variable to generate unique symbols
+counter :: IORef Int
+{-# NOINLINE counter #-}
+counter = unsafePerformIO (newIORef 0)
+
+
+-----------------------------------------------------
+--
+-- The Q monad
+--
+-----------------------------------------------------
+
+newtype Q a = Q { unQ :: forall m. Quasi m => m a }
+
+-- \"Runs\" the 'Q' monad. Normal users of Template Haskell
+-- should not need this function, as the splice brackets @$( ... )@
+-- are the usual way of running a 'Q' computation.
+--
+-- This function is primarily used in GHC internals, and for debugging
+-- splices by running them in 'IO'.
+--
+-- Note that many functions in 'Q', such as 'reify' and other compiler
+-- queries, are not supported when running 'Q' in 'IO'; these operations
+-- simply fail at runtime. Indeed, the only operations guaranteed to succeed
+-- are 'newName', 'runIO', 'reportError' and 'reportWarning'.
+runQ :: Quasi m => Q a -> m a
+runQ (Q m) = m
+
+instance Monad Q where
+ return x = Q (return x)
+ Q m >>= k = Q (m >>= \x -> unQ (k x))
+ Q m >> Q n = Q (m >> n)
+ fail s = report True s >> Q (fail "Q monad failure")
+
+instance Functor Q where
+ fmap f (Q x) = Q (fmap f x)
+
+instance Applicative Q where
+ pure x = Q (pure x)
+ Q f <*> Q x = Q (f <*> x)
+
+-----------------------------------------------------
+--
+-- The TExp type
+--
+-----------------------------------------------------
+
+type role TExp nominal -- See Note [Role of TExp]
+newtype TExp a = TExp { unType :: Exp }
+
+unTypeQ :: Q (TExp a) -> Q Exp
+unTypeQ m = do { TExp e <- m
+ ; return e }
+
+unsafeTExpCoerce :: Q Exp -> Q (TExp a)
+unsafeTExpCoerce m = do { e <- m
+ ; return (TExp e) }
+
+{- Note [Role of TExp]
+~~~~~~~~~~~~~~~~~~~~~~
+TExp's argument must have a nominal role, not phantom as would
+be inferred (Trac #8459). Consider
+
+ e :: TExp Age
+ e = MkAge 3
+
+ foo = $(coerce e) + 4::Int
+
+The splice will evaluate to (MkAge 3) and you can't add that to
+4::Int. So you can't coerce a (TExp Age) to a (TExp Int). -}
+
+----------------------------------------------------
+-- Packaged versions for the programmer, hiding the Quasi-ness
+
+{- |
+Generate a fresh name, which cannot be captured.
+
+For example, this:
+
+@f = $(do
+ nm1 <- newName \"x\"
+ let nm2 = 'mkName' \"x\"
+ return ('LamE' ['VarP' nm1] (LamE [VarP nm2] ('VarE' nm1)))
+ )@
+
+will produce the splice
+
+>f = \x0 -> \x -> x0
+
+In particular, the occurrence @VarE nm1@ refers to the binding @VarP nm1@,
+and is not captured by the binding @VarP nm2@.
+
+Although names generated by @newName@ cannot /be captured/, they can
+/capture/ other names. For example, this:
+
+>g = $(do
+> nm1 <- newName "x"
+> let nm2 = mkName "x"
+> return (LamE [VarP nm2] (LamE [VarP nm1] (VarE nm2)))
+> )
+
+will produce the splice
+
+>g = \x -> \x0 -> x0
+
+since the occurrence @VarE nm2@ is captured by the innermost binding
+of @x@, namely @VarP nm1@.
+-}
+newName :: String -> Q Name
+newName s = Q (qNewName s)
+
+-- | Report an error (True) or warning (False),
+-- but carry on; use 'fail' to stop.
+report :: Bool -> String -> Q ()
+report b s = Q (qReport b s)
+{-# DEPRECATED report "Use reportError or reportWarning instead" #-} -- deprecated in 7.6
+
+-- | Report an error to the user, but allow the current splice's computation to carry on. To abort the computation, use 'fail'.
+reportError :: String -> Q ()
+reportError = report True
+
+-- | Report a warning to the user, and carry on.
+reportWarning :: String -> Q ()
+reportWarning = report False
+
+-- | Recover from errors raised by 'reportError' or 'fail'.
+recover :: Q a -- ^ handler to invoke on failure
+ -> Q a -- ^ computation to run
+ -> Q a
+recover (Q r) (Q m) = Q (qRecover r m)
+
+-- We don't export lookupName; the Bool isn't a great API
+-- Instead we export lookupTypeName, lookupValueName
+lookupName :: Bool -> String -> Q (Maybe Name)
+lookupName ns s = Q (qLookupName ns s)
+
+-- | Look up the given name in the (type namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
+lookupTypeName :: String -> Q (Maybe Name)
+lookupTypeName s = Q (qLookupName True s)
+
+-- | Look up the given name in the (value namespace of the) current splice's scope. See "Language.Haskell.TH.Syntax#namelookup" for more details.
+lookupValueName :: String -> Q (Maybe Name)
+lookupValueName s = Q (qLookupName False s)
+
+{-
+Note [Name lookup]
+~~~~~~~~~~~~~~~~~~
+-}
+{- $namelookup #namelookup#
+The functions 'lookupTypeName' and 'lookupValueName' provide
+a way to query the current splice's context for what names
+are in scope. The function 'lookupTypeName' queries the type
+namespace, whereas 'lookupValueName' queries the value namespace,
+but the functions are otherwise identical.
+
+A call @lookupValueName s@ will check if there is a value
+with name @s@ in scope at the current splice's location. If
+there is, the @Name@ of this value is returned;
+if not, then @Nothing@ is returned.
+
+The returned name cannot be \"captured\".
+For example:
+
+> f = "global"
+> g = $( do
+> Just nm <- lookupValueName "f"
+> [| let f = "local" in $( varE nm ) |]
+
+In this case, @g = \"global\"@; the call to @lookupValueName@
+returned the global @f@, and this name was /not/ captured by
+the local definition of @f@.
+
+The lookup is performed in the context of the /top-level/ splice
+being run. For example:
+
+> f = "global"
+> g = $( [| let f = "local" in
+> $(do
+> Just nm <- lookupValueName "f"
+> varE nm
+> ) |] )
+
+Again in this example, @g = \"global\"@, because the call to
+@lookupValueName@ queries the context of the outer-most @$(...)@.
+
+Operators should be queried without any surrounding parentheses, like so:
+
+> lookupValueName "+"
+
+Qualified names are also supported, like so:
+
+> lookupValueName "Prelude.+"
+> lookupValueName "Prelude.map"
+
+-}
+
+
+{- | 'reify' looks up information about the 'Name'.
+
+It is sometimes useful to construct the argument name using 'lookupTypeName' or 'lookupValueName'
+to ensure that we are reifying from the right namespace. For instance, in this context:
+
+> data D = D
+
+which @D@ does @reify (mkName \"D\")@ return information about? (Answer: @D@-the-type, but don't rely on it.)
+To ensure we get information about @D@-the-value, use 'lookupValueName':
+
+> do
+> Just nm <- lookupValueName "D"
+> reify nm
+
+and to get information about @D@-the-type, use 'lookupTypeName'.
+-}
+reify :: Name -> Q Info
+reify v = Q (qReify v)
+
+{- | @reifyInstances nm tys@ returns a list of visible instances of @nm tys@. That is,
+if @nm@ is the name of a type class, then all instances of this class at the types @tys@
+are returned. Alternatively, if @nm@ is the name of a data family or type family,
+all instances of this family at the types @tys@ are returned.
+-}
+reifyInstances :: Name -> [Type] -> Q [InstanceDec]
+reifyInstances cls tys = Q (qReifyInstances cls tys)
+
+{- | @reifyRoles nm@ returns the list of roles associated with the parameters of
+the tycon @nm@. Fails if @nm@ cannot be found or is not a tycon.
+The returned list should never contain 'InferR'.
+-}
+reifyRoles :: Name -> Q [Role]
+reifyRoles nm = Q (qReifyRoles nm)
+
+-- | @reifyAnnotations target@ returns the list of annotations
+-- associated with @target@. Only the annotations that are
+-- appropriately typed is returned. So if you have @Int@ and @String@
+-- annotations for the same target, you have to call this function twice.
+reifyAnnotations :: Data a => AnnLookup -> Q [a]
+reifyAnnotations an = Q (qReifyAnnotations an)
+
+-- | @reifyModule mod@ looks up information about module @mod@. To
+-- look up the current module, call this function with the return
+-- value of @thisModule@.
+reifyModule :: Module -> Q ModuleInfo
+reifyModule m = Q (qReifyModule m)
+
+-- | Is the list of instances returned by 'reifyInstances' nonempty?
+isInstance :: Name -> [Type] -> Q Bool
+isInstance nm tys = do { decs <- reifyInstances nm tys
+ ; return (not (null decs)) }
+
+-- | The location at which this computation is spliced.
+location :: Q Loc
+location = Q qLocation
+
+-- |The 'runIO' function lets you run an I\/O computation in the 'Q' monad.
+-- Take care: you are guaranteed the ordering of calls to 'runIO' within
+-- a single 'Q' computation, but not about the order in which splices are run.
+--
+-- Note: for various murky reasons, stdout and stderr handles are not
+-- necessarily flushed when the compiler finishes running, so you should
+-- flush them yourself.
+runIO :: IO a -> Q a
+runIO m = Q (qRunIO m)
+
+-- | Record external files that runIO is using (dependent upon).
+-- The compiler can then recognize that it should re-compile the file using this TH when the external file changes.
+-- Note that ghc -M will still not know about these dependencies - it does not execute TH.
+-- Expects an absolute file path.
+addDependentFile :: FilePath -> Q ()
+addDependentFile fp = Q (qAddDependentFile fp)
+
+-- | Add additional top-level declarations. The added declarations will be type
+-- checked along with the current declaration group.
+addTopDecls :: [Dec] -> Q ()
+addTopDecls ds = Q (qAddTopDecls ds)
+
+-- | Add a finalizer that will run in the Q monad after the current module has
+-- been type checked. This only makes sense when run within a top-level splice.
+addModFinalizer :: Q () -> Q ()
+addModFinalizer act = Q (qAddModFinalizer (unQ act))
+
+-- | Get state from the Q monad.
+getQ :: Typeable a => Q (Maybe a)
+getQ = Q qGetQ
+
+-- | Replace the state in the Q monad.
+putQ :: Typeable a => a -> Q ()
+putQ x = Q (qPutQ x)
+
+instance Quasi Q where
+ qNewName = newName
+ qReport = report
+ qRecover = recover
+ qReify = reify
+ qReifyInstances = reifyInstances
+ qReifyRoles = reifyRoles
+ qReifyAnnotations = reifyAnnotations
+ qReifyModule = reifyModule
+ qLookupName = lookupName
+ qLocation = location
+ qRunIO = runIO
+ qAddDependentFile = addDependentFile
+ qAddTopDecls = addTopDecls
+ qAddModFinalizer = addModFinalizer
+ qGetQ = getQ
+ qPutQ = putQ
+
+
+----------------------------------------------------
+-- The following operations are used solely in DsMeta when desugaring brackets
+-- They are not necessary for the user, who can use ordinary return and (>>=) etc
+
+returnQ :: a -> Q a
+returnQ = return
+
+bindQ :: Q a -> (a -> Q b) -> Q b
+bindQ = (>>=)
+
+sequenceQ :: [Q a] -> Q [a]
+sequenceQ = sequence
+
+
+-----------------------------------------------------
+--
+-- The Lift class
+--
+-----------------------------------------------------
+
+class Lift t where
+ lift :: t -> Q Exp
+
+instance Lift Integer where
+ lift x = return (LitE (IntegerL x))
+
+instance Lift Int where
+ lift x= return (LitE (IntegerL (fromIntegral x)))
+
+instance Lift Char where
+ lift x = return (LitE (CharL x))
+
+instance Lift Bool where
+ lift True = return (ConE trueName)
+ lift False = return (ConE falseName)
+
+instance Lift a => Lift (Maybe a) where
+ lift Nothing = return (ConE nothingName)
+ lift (Just x) = liftM (ConE justName `AppE`) (lift x)
+
+instance (Lift a, Lift b) => Lift (Either a b) where
+ lift (Left x) = liftM (ConE leftName `AppE`) (lift x)
+ lift (Right y) = liftM (ConE rightName `AppE`) (lift y)
+
+instance Lift a => Lift [a] where
+ lift xs = do { xs' <- mapM lift xs; return (ListE xs') }
+
+liftString :: String -> Q Exp
+-- Used in TcExpr to short-circuit the lifting for strings
+liftString s = return (LitE (StringL s))
+
+instance (Lift a, Lift b) => Lift (a, b) where
+ lift (a, b)
+ = liftM TupE $ sequence [lift a, lift b]
+
+instance (Lift a, Lift b, Lift c) => Lift (a, b, c) where
+ lift (a, b, c)
+ = liftM TupE $ sequence [lift a, lift b, lift c]
+
+instance (Lift a, Lift b, Lift c, Lift d) => Lift (a, b, c, d) where
+ lift (a, b, c, d)
+ = liftM TupE $ sequence [lift a, lift b, lift c, lift d]
+
+instance (Lift a, Lift b, Lift c, Lift d, Lift e)
+ => Lift (a, b, c, d, e) where
+ lift (a, b, c, d, e)
+ = liftM TupE $ sequence [lift a, lift b, lift c, lift d, lift e]
+
+instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f)
+ => Lift (a, b, c, d, e, f) where
+ lift (a, b, c, d, e, f)
+ = liftM TupE $ sequence [lift a, lift b, lift c, lift d, lift e, lift f]
+
+instance (Lift a, Lift b, Lift c, Lift d, Lift e, Lift f, Lift g)
+ => Lift (a, b, c, d, e, f, g) where
+ lift (a, b, c, d, e, f, g)
+ = liftM TupE $ sequence [lift a, lift b, lift c, lift d, lift e, lift f, lift g]
+
+-- TH has a special form for literal strings,
+-- which we should take advantage of.
+-- NB: the lhs of the rule has no args, so that
+-- the rule will apply to a 'lift' all on its own
+-- which happens to be the way the type checker
+-- creates it.
+{-# RULES "TH:liftString" lift = \s -> return (LitE (StringL s)) #-}
+
+
+trueName, falseName :: Name
+trueName = mkNameG DataName "ghc-prim" "GHC.Types" "True"
+falseName = mkNameG DataName "ghc-prim" "GHC.Types" "False"
+
+nothingName, justName :: Name
+nothingName = mkNameG DataName "base" "Data.Maybe" "Nothing"
+justName = mkNameG DataName "base" "Data.Maybe" "Just"
+
+leftName, rightName :: Name
+leftName = mkNameG DataName "base" "Data.Either" "Left"
+rightName = mkNameG DataName "base" "Data.Either" "Right"
+
+
+-----------------------------------------------------
+-- Names and uniques
+-----------------------------------------------------
+
+newtype ModName = ModName String -- Module name
+ deriving (Show,Eq,Ord,Typeable,Data)
+
+newtype PkgName = PkgName String -- package name
+ deriving (Show,Eq,Ord,Typeable,Data)
+
+-- | Obtained from 'reifyModule' and 'thisModule'.
+data Module = Module PkgName ModName -- package qualified module name
+ deriving (Show,Eq,Ord,Typeable,Data)
+
+newtype OccName = OccName String
+ deriving (Show,Eq,Ord,Typeable,Data)
+
+mkModName :: String -> ModName
+mkModName s = ModName s
+
+modString :: ModName -> String
+modString (ModName m) = m
+
+
+mkPkgName :: String -> PkgName
+mkPkgName s = PkgName s
+
+pkgString :: PkgName -> String
+pkgString (PkgName m) = m
+
+
+-----------------------------------------------------
+-- OccName
+-----------------------------------------------------
+
+mkOccName :: String -> OccName
+mkOccName s = OccName s
+
+occString :: OccName -> String
+occString (OccName occ) = occ
+
+
+-----------------------------------------------------
+-- Names
+-----------------------------------------------------
+--
+-- For "global" names ('NameG') we need a totally unique name,
+-- so we must include the name-space of the thing
+--
+-- For unique-numbered things ('NameU'), we've got a unique reference
+-- anyway, so no need for name space
+--
+-- For dynamically bound thing ('NameS') we probably want them to
+-- in a context-dependent way, so again we don't want the name
+-- space. For example:
+--
+-- > let v = mkName "T" in [| data $v = $v |]
+--
+-- Here we use the same Name for both type constructor and data constructor
+--
+--
+-- NameL and NameG are bound *outside* the TH syntax tree
+-- either globally (NameG) or locally (NameL). Ex:
+--
+-- > f x = $(h [| (map, x) |])
+--
+-- The 'map' will be a NameG, and 'x' wil be a NameL
+--
+-- These Names should never appear in a binding position in a TH syntax tree
+
+{- $namecapture #namecapture#
+Much of 'Name' API is concerned with the problem of /name capture/, which
+can be seen in the following example.
+
+> f expr = [| let x = 0 in $expr |]
+> ...
+> g x = $( f [| x |] )
+> h y = $( f [| y |] )
+
+A naive desugaring of this would yield:
+
+> g x = let x = 0 in x
+> h y = let x = 0 in y
+
+All of a sudden, @g@ and @h@ have different meanings! In this case,
+we say that the @x@ in the RHS of @g@ has been /captured/
+by the binding of @x@ in @f@.
+
+What we actually want is for the @x@ in @f@ to be distinct from the
+@x@ in @g@, so we get the following desugaring:
+
+> g x = let x' = 0 in x
+> h y = let x' = 0 in y
+
+which avoids name capture as desired.
+
+In the general case, we say that a @Name@ can be captured if
+the thing it refers to can be changed by adding new declarations.
+-}
+
+{- |
+An abstract type representing names in the syntax tree.
+
+'Name's can be constructed in several ways, which come with different
+name-capture guarantees (see "Language.Haskell.TH.Syntax#namecapture" for
+an explanation of name capture):
+
+ * the built-in syntax @'f@ and @''T@ can be used to construct names,
+ The expression @'f@ gives a @Name@ which refers to the value @f@
+ currently in scope, and @''T@ gives a @Name@ which refers to the
+ type @T@ currently in scope. These names can never be captured.
+
+ * 'lookupValueName' and 'lookupTypeName' are similar to @'f@ and
+ @''T@ respectively, but the @Name@s are looked up at the point
+ where the current splice is being run. These names can never be
+ captured.
+
+ * 'newName' monadically generates a new name, which can never
+ be captured.
+
+ * 'mkName' generates a capturable name.
+
+Names constructed using @newName@ and @mkName@ may be used in bindings
+(such as @let x = ...@ or @\x -> ...@), but names constructed using
+@lookupValueName@, @lookupTypeName@, @'f@, @''T@ may not.
+-}
+data Name = Name OccName NameFlavour deriving (Typeable, Data)
+
+data NameFlavour
+ = NameS -- ^ An unqualified name; dynamically bound
+ | NameQ ModName -- ^ A qualified name; dynamically bound
+ | NameU Int# -- ^ A unique local name
+ | NameL Int# -- ^ Local name bound outside of the TH AST
+ | NameG NameSpace PkgName ModName -- ^ Global name bound outside of the TH AST:
+ -- An original name (occurrences only, not binders)
+ -- Need the namespace too to be sure which
+ -- thing we are naming
+ deriving ( Typeable )
+
+-- |
+-- Although the NameFlavour type is abstract, the Data instance is not. The reason for this
+-- is that currently we use Data to serialize values in annotations, and in order for that to
+-- work for Template Haskell names introduced via the 'x syntax we need gunfold on NameFlavour
+-- to work. Bleh!
+--
+-- The long term solution to this is to use the binary package for annotation serialization and
+-- then remove this instance. However, to do _that_ we need to wait on binary to become stable, since
+-- boot libraries cannot be upgraded separately from GHC itself.
+--
+-- This instance cannot be derived automatically due to bug #2701
+instance Data NameFlavour where
+ gfoldl _ z NameS = z NameS
+ gfoldl k z (NameQ mn) = z NameQ `k` mn
+ gfoldl k z (NameU i) = z (\(I# i') -> NameU i') `k` (I# i)
+ gfoldl k z (NameL i) = z (\(I# i') -> NameL i') `k` (I# i)
+ gfoldl k z (NameG ns p m) = z NameG `k` ns `k` p `k` m
+ gunfold k z c = case constrIndex c of
+ 1 -> z NameS
+ 2 -> k $ z NameQ
+ 3 -> k $ z (\(I# i) -> NameU i)
+ 4 -> k $ z (\(I# i) -> NameL i)
+ 5 -> k $ k $ k $ z NameG
+ _ -> error "gunfold: NameFlavour"
+ toConstr NameS = con_NameS
+ toConstr (NameQ _) = con_NameQ
+ toConstr (NameU _) = con_NameU
+ toConstr (NameL _) = con_NameL
+ toConstr (NameG _ _ _) = con_NameG
+ dataTypeOf _ = ty_NameFlavour
+
+con_NameS, con_NameQ, con_NameU, con_NameL, con_NameG :: Data.Constr
+con_NameS = mkConstr ty_NameFlavour "NameS" [] Data.Prefix
+con_NameQ = mkConstr ty_NameFlavour "NameQ" [] Data.Prefix
+con_NameU = mkConstr ty_NameFlavour "NameU" [] Data.Prefix
+con_NameL = mkConstr ty_NameFlavour "NameL" [] Data.Prefix
+con_NameG = mkConstr ty_NameFlavour "NameG" [] Data.Prefix
+
+ty_NameFlavour :: Data.DataType
+ty_NameFlavour = mkDataType "Language.Haskell.TH.Syntax.NameFlavour"
+ [con_NameS, con_NameQ, con_NameU,
+ con_NameL, con_NameG]
+
+data NameSpace = VarName -- ^ Variables
+ | DataName -- ^ Data constructors
+ | TcClsName -- ^ Type constructors and classes; Haskell has them
+ -- in the same name space for now.
+ deriving( Eq, Ord, Data, Typeable )
+
+type Uniq = Int
+
+-- | The name without its module prefix
+nameBase :: Name -> String
+nameBase (Name occ _) = occString occ
+
+-- | Module prefix of a name, if it exists
+nameModule :: Name -> Maybe String
+nameModule (Name _ (NameQ m)) = Just (modString m)
+nameModule (Name _ (NameG _ _ m)) = Just (modString m)
+nameModule _ = Nothing
+
+{- |
+Generate a capturable name. Occurrences of such names will be
+resolved according to the Haskell scoping rules at the occurrence
+site.
+
+For example:
+
+> f = [| pi + $(varE (mkName "pi")) |]
+> ...
+> g = let pi = 3 in $f
+
+In this case, @g@ is desugared to
+
+> g = Prelude.pi + 3
+
+Note that @mkName@ may be used with qualified names:
+
+> mkName "Prelude.pi"
+
+See also 'Language.Haskell.TH.Lib.dyn' for a useful combinator. The above example could
+be rewritten using 'dyn' as
+
+> f = [| pi + $(dyn "pi") |]
+-}
+mkName :: String -> Name
+-- The string can have a '.', thus "Foo.baz",
+-- giving a dynamically-bound qualified name,
+-- in which case we want to generate a NameQ
+--
+-- Parse the string to see if it has a "." in it
+-- so we know whether to generate a qualified or unqualified name
+-- It's a bit tricky because we need to parse
+--
+-- > Foo.Baz.x as Qual Foo.Baz x
+--
+-- So we parse it from back to front
+mkName str
+ = split [] (reverse str)
+ where
+ split occ [] = Name (mkOccName occ) NameS
+ split occ ('.':rev) | not (null occ)
+ , is_rev_mod_name rev
+ = Name (mkOccName occ) (NameQ (mkModName (reverse rev)))
+ -- The 'not (null occ)' guard ensures that
+ -- mkName "&." = Name "&." NameS
+ -- The 'is_rev_mod' guards ensure that
+ -- mkName ".&" = Name ".&" NameS
+ -- mkName "^.." = Name "^.." NameS -- Trac #8633
+ -- mkName "Data.Bits..&" = Name ".&" (NameQ "Data.Bits")
+ -- This rather bizarre case actually happened; (.&.) is in Data.Bits
+ split occ (c:rev) = split (c:occ) rev
+
+ -- Recognises a reversed module name xA.yB.C,
+ -- with at least one component,
+ -- and each component looks like a module name
+ -- (i.e. non-empty, starts with capital, all alpha)
+ is_rev_mod_name rev_mod_str
+ | (compt, rest) <- break (== '.') rev_mod_str
+ , not (null compt), isUpper (last compt), all is_mod_char compt
+ = case rest of
+ [] -> True
+ (_dot : rest') -> is_rev_mod_name rest'
+ | otherwise
+ = False
+
+ is_mod_char c = isAlphaNum c || c == '_' || c == '\''
+
+-- | Only used internally
+mkNameU :: String -> Uniq -> Name
+mkNameU s (I# u) = Name (mkOccName s) (NameU u)
+
+-- | Only used internally
+mkNameL :: String -> Uniq -> Name
+mkNameL s (I# u) = Name (mkOccName s) (NameL u)
+
+-- | Used for 'x etc, but not available to the programmer
+mkNameG :: NameSpace -> String -> String -> String -> Name
+mkNameG ns pkg modu occ
+ = Name (mkOccName occ) (NameG ns (mkPkgName pkg) (mkModName modu))
+
+mkNameG_v, mkNameG_tc, mkNameG_d :: String -> String -> String -> Name
+mkNameG_v = mkNameG VarName
+mkNameG_tc = mkNameG TcClsName
+mkNameG_d = mkNameG DataName
+
+instance Eq Name where
+ v1 == v2 = cmpEq (v1 `compare` v2)
+
+instance Ord Name where
+ (Name o1 f1) `compare` (Name o2 f2) = (f1 `compare` f2) `thenCmp`
+ (o1 `compare` o2)
+
+instance Eq NameFlavour where
+ f1 == f2 = cmpEq (f1 `compare` f2)
+
+instance Ord NameFlavour where
+ -- NameS < NameQ < NameU < NameL < NameG
+ NameS `compare` NameS = EQ
+ NameS `compare` _ = LT
+
+ (NameQ _) `compare` NameS = GT
+ (NameQ m1) `compare` (NameQ m2) = m1 `compare` m2
+ (NameQ _) `compare` _ = LT
+
+ (NameU _) `compare` NameS = GT
+ (NameU _) `compare` (NameQ _) = GT
+ (NameU u1) `compare` (NameU u2) | isTrue# (u1 <# u2) = LT
+ | isTrue# (u1 ==# u2) = EQ
+ | otherwise = GT
+ (NameU _) `compare` _ = LT
+
+ (NameL _) `compare` NameS = GT
+ (NameL _) `compare` (NameQ _) = GT
+ (NameL _) `compare` (NameU _) = GT
+ (NameL u1) `compare` (NameL u2) | isTrue# (u1 <# u2) = LT
+ | isTrue# (u1 ==# u2) = EQ
+ | otherwise = GT
+ (NameL _) `compare` _ = LT
+
+ (NameG ns1 p1 m1) `compare` (NameG ns2 p2 m2) = (ns1 `compare` ns2) `thenCmp`
+ (p1 `compare` p2) `thenCmp`
+ (m1 `compare` m2)
+ (NameG _ _ _) `compare` _ = GT
+
+data NameIs = Alone | Applied | Infix
+
+showName :: Name -> String
+showName = showName' Alone
+
+showName' :: NameIs -> Name -> String
+showName' ni nm
+ = case ni of
+ Alone -> nms
+ Applied
+ | pnam -> nms
+ | otherwise -> "(" ++ nms ++ ")"
+ Infix
+ | pnam -> "`" ++ nms ++ "`"
+ | otherwise -> nms
+ where
+ -- For now, we make the NameQ and NameG print the same, even though
+ -- NameQ is a qualified name (so what it means depends on what the
+ -- current scope is), and NameG is an original name (so its meaning
+ -- should be independent of what's in scope.
+ -- We may well want to distinguish them in the end.
+ -- Ditto NameU and NameL
+ nms = case nm of
+ Name occ NameS -> occString occ
+ Name occ (NameQ m) -> modString m ++ "." ++ occString occ
+ Name occ (NameG _ _ m) -> modString m ++ "." ++ occString occ
+ Name occ (NameU u) -> occString occ ++ "_" ++ show (I# u)
+ Name occ (NameL u) -> occString occ ++ "_" ++ show (I# u)
+
+ pnam = classify nms
+
+ -- True if we are function style, e.g. f, [], (,)
+ -- False if we are operator style, e.g. +, :+
+ classify "" = False -- shouldn't happen; . operator is handled below
+ classify (x:xs) | isAlpha x || (x `elem` "_[]()") =
+ case dropWhile (/='.') xs of
+ (_:xs') -> classify xs'
+ [] -> True
+ | otherwise = False
+
+instance Show Name where
+ show = showName
+
+-- Tuple data and type constructors
+-- | Tuple data constructor
+tupleDataName :: Int -> Name
+-- | Tuple type constructor
+tupleTypeName :: Int -> Name
+
+tupleDataName 0 = mk_tup_name 0 DataName
+tupleDataName 1 = error "tupleDataName 1"
+tupleDataName n = mk_tup_name (n-1) DataName
+
+tupleTypeName 0 = mk_tup_name 0 TcClsName
+tupleTypeName 1 = error "tupleTypeName 1"
+tupleTypeName n = mk_tup_name (n-1) TcClsName
+
+mk_tup_name :: Int -> NameSpace -> Name
+mk_tup_name n_commas space
+ = Name occ (NameG space (mkPkgName "ghc-prim") tup_mod)
+ where
+ occ = mkOccName ('(' : replicate n_commas ',' ++ ")")
+ tup_mod = mkModName "GHC.Tuple"
+
+-- Unboxed tuple data and type constructors
+-- | Unboxed tuple data constructor
+unboxedTupleDataName :: Int -> Name
+-- | Unboxed tuple type constructor
+unboxedTupleTypeName :: Int -> Name
+
+unboxedTupleDataName 0 = error "unboxedTupleDataName 0"
+unboxedTupleDataName 1 = error "unboxedTupleDataName 1"
+unboxedTupleDataName n = mk_unboxed_tup_name (n-1) DataName
+
+unboxedTupleTypeName 0 = error "unboxedTupleTypeName 0"
+unboxedTupleTypeName 1 = error "unboxedTupleTypeName 1"
+unboxedTupleTypeName n = mk_unboxed_tup_name (n-1) TcClsName
+
+mk_unboxed_tup_name :: Int -> NameSpace -> Name
+mk_unboxed_tup_name n_commas space
+ = Name occ (NameG space (mkPkgName "ghc-prim") tup_mod)
+ where
+ occ = mkOccName ("(#" ++ replicate n_commas ',' ++ "#)")
+ tup_mod = mkModName "GHC.Tuple"
+
+
+
+-----------------------------------------------------
+-- Locations
+-----------------------------------------------------
+
+data Loc
+ = Loc { loc_filename :: String
+ , loc_package :: String
+ , loc_module :: String
+ , loc_start :: CharPos
+ , loc_end :: CharPos }
+
+type CharPos = (Int, Int) -- ^ Line and character position
+
+
+-----------------------------------------------------
+--
+-- The Info returned by reification
+--
+-----------------------------------------------------
+
+-- | Obtained from 'reify' in the 'Q' Monad.
+data Info
+ =
+ -- | A class, with a list of its visible instances
+ ClassI
+ Dec
+ [InstanceDec]
+
+ -- | A class method
+ | ClassOpI
+ Name
+ Type
+ ParentName
+ Fixity
+
+ -- | A \"plain\" type constructor. \"Fancier\" type constructors are returned using 'PrimTyConI' or 'FamilyI' as appropriate
+ | TyConI
+ Dec
+
+ -- | A type or data family, with a list of its visible instances. A closed
+ -- type family is returned with 0 instances.
+ | FamilyI
+ Dec
+ [InstanceDec]
+
+ -- | A \"primitive\" type constructor, which can't be expressed with a 'Dec'. Examples: @(->)@, @Int#@.
+ | PrimTyConI
+ Name
+ Arity
+ Unlifted
+
+ -- | A data constructor
+ | DataConI
+ Name
+ Type
+ ParentName
+ Fixity
+
+ {- |
+ A \"value\" variable (as opposed to a type variable, see 'TyVarI').
+
+ The @Maybe Dec@ field contains @Just@ the declaration which
+ defined the variable -- including the RHS of the declaration --
+ or else @Nothing@, in the case where the RHS is unavailable to
+ the compiler. At present, this value is _always_ @Nothing@:
+ returning the RHS has not yet been implemented because of
+ lack of interest.
+ -}
+ | VarI
+ Name
+ Type
+ (Maybe Dec)
+ Fixity
+
+ {- |
+ A type variable.
+
+ The @Type@ field contains the type which underlies the variable.
+ At present, this is always @'VarT' theName@, but future changes
+ may permit refinement of this.
+ -}
+ | TyVarI -- Scoped type variable
+ Name
+ Type -- What it is bound to
+ deriving( Show, Data, Typeable )
+
+-- | Obtained from 'reifyModule' in the 'Q' Monad.
+data ModuleInfo =
+ -- | Contains the import list of the module.
+ ModuleInfo [Module]
+ deriving( Show, Data, Typeable )
+
+{- |
+In 'ClassOpI' and 'DataConI', name of the parent class or type
+-}
+type ParentName = Name
+
+-- | In 'PrimTyConI', arity of the type constructor
+type Arity = Int
+
+-- | In 'PrimTyConI', is the type constructor unlifted?
+type Unlifted = Bool
+
+-- | 'InstanceDec' desribes a single instance of a class or type function.
+-- It is just a 'Dec', but guaranteed to be one of the following:
+--
+-- * 'InstanceD' (with empty @['Dec']@)
+--
+-- * 'DataInstD' or 'NewtypeInstD' (with empty derived @['Name']@)
+--
+-- * 'TySynInstD'
+type InstanceDec = Dec
+
+data Fixity = Fixity Int FixityDirection
+ deriving( Eq, Show, Data, Typeable )
+data FixityDirection = InfixL | InfixR | InfixN
+ deriving( Eq, Show, Data, Typeable )
+
+-- | Highest allowed operator precedence for 'Fixity' constructor (answer: 9)
+maxPrecedence :: Int
+maxPrecedence = (9::Int)
+
+-- | Default fixity: @infixl 9@
+defaultFixity :: Fixity
+defaultFixity = Fixity maxPrecedence InfixL
+
+
+{-
+Note [Unresolved infix]
+~~~~~~~~~~~~~~~~~~~~~~~
+-}
+{- $infix #infix#
+When implementing antiquotation for quasiquoters, one often wants
+to parse strings into expressions:
+
+> parse :: String -> Maybe Exp
+
+But how should we parse @a + b * c@? If we don't know the fixities of
+@+@ and @*@, we don't know whether to parse it as @a + (b * c)@ or @(a
++ b) * c@.
+
+In cases like this, use 'UInfixE' or 'UInfixP', which stand for
+\"unresolved infix expression\" and \"unresolved infix pattern\". When
+the compiler is given a splice containing a tree of @UInfixE@
+applications such as
+
+> UInfixE
+> (UInfixE e1 op1 e2)
+> op2
+> (UInfixE e3 op3 e4)
+
+it will look up and the fixities of the relevant operators and
+reassociate the tree as necessary.
+
+ * trees will not be reassociated across 'ParensE' or 'ParensP',
+ which are of use for parsing expressions like
+
+ > (a + b * c) + d * e
+
+ * 'InfixE' and 'InfixP' expressions are never reassociated.
+
+ * The 'UInfixE' constructor doesn't support sections. Sections
+ such as @(a *)@ have no ambiguity, so 'InfixE' suffices. For longer
+ sections such as @(a + b * c -)@, use an 'InfixE' constructor for the
+ outer-most section, and use 'UInfixE' constructors for all
+ other operators:
+
+ > InfixE
+ > Just (UInfixE ...a + b * c...)
+ > op
+ > Nothing
+
+ Sections such as @(a + b +)@ and @((a + b) +)@ should be rendered
+ into 'Exp's differently:
+
+ > (+ a + b) ---> InfixE Nothing + (Just $ UInfixE a + b)
+ > -- will result in a fixity error if (+) is left-infix
+ > (+ (a + b)) ---> InfixE Nothing + (Just $ ParensE $ UInfixE a + b)
+ > -- no fixity errors
+
+ * Quoted expressions such as
+
+ > [| a * b + c |] :: Q Exp
+ > [p| a : b : c |] :: Q Pat
+
+ will never contain 'UInfixE', 'UInfixP', 'ParensE', or 'ParensP'
+ constructors.
+
+-}
+
+-----------------------------------------------------
+--
+-- The main syntax data types
+--
+-----------------------------------------------------
+
+data Lit = CharL Char
+ | StringL String
+ | IntegerL Integer -- ^ Used for overloaded and non-overloaded
+ -- literals. We don't have a good way to
+ -- represent non-overloaded literals at
+ -- the moment. Maybe that doesn't matter?
+ | RationalL Rational -- Ditto
+ | IntPrimL Integer
+ | WordPrimL Integer
+ | FloatPrimL Rational
+ | DoublePrimL Rational
+ | StringPrimL [Word8] -- ^ A primitive C-style string, type Addr#
+ deriving( Show, Eq, Data, Typeable )
+
+ -- We could add Int, Float, Double etc, as we do in HsLit,
+ -- but that could complicate the
+ -- suppposedly-simple TH.Syntax literal type
+
+-- | Pattern in Haskell given in @{}@
+data Pat
+ = LitP Lit -- ^ @{ 5 or 'c' }@
+ | VarP Name -- ^ @{ x }@
+ | TupP [Pat] -- ^ @{ (p1,p2) }@
+ | UnboxedTupP [Pat] -- ^ @{ (# p1,p2 #) }@
+ | ConP Name [Pat] -- ^ @data T1 = C1 t1 t2; {C1 p1 p1} = e@
+ | InfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
+ | UInfixP Pat Name Pat -- ^ @foo ({x :+ y}) = e@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | ParensP Pat -- ^ @{(p)}@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | TildeP Pat -- ^ @{ ~p }@
+ | BangP Pat -- ^ @{ !p }@
+ | AsP Name Pat -- ^ @{ x \@ p }@
+ | WildP -- ^ @{ _ }@
+ | RecP Name [FieldPat] -- ^ @f (Pt { pointx = x }) = g x@
+ | ListP [ Pat ] -- ^ @{ [1,2,3] }@
+ | SigP Pat Type -- ^ @{ p :: t }@
+ | ViewP Exp Pat -- ^ @{ e -> p }@
+ deriving( Show, Eq, Data, Typeable )
+
+type FieldPat = (Name,Pat)
+
+data Match = Match Pat Body [Dec] -- ^ @case e of { pat -> body where decs }@
+ deriving( Show, Eq, Data, Typeable )
+data Clause = Clause [Pat] Body [Dec]
+ -- ^ @f { p1 p2 = body where decs }@
+ deriving( Show, Eq, Data, Typeable )
+
+data Exp
+ = VarE Name -- ^ @{ x }@
+ | ConE Name -- ^ @data T1 = C1 t1 t2; p = {C1} e1 e2 @
+ | LitE Lit -- ^ @{ 5 or 'c'}@
+ | AppE Exp Exp -- ^ @{ f x }@
+
+ | InfixE (Maybe Exp) Exp (Maybe Exp) -- ^ @{x + y} or {(x+)} or {(+ x)} or {(+)}@
+
+ -- It's a bit gruesome to use an Exp as the
+ -- operator, but how else can we distinguish
+ -- constructors from non-constructors?
+ -- Maybe there should be a var-or-con type?
+ -- Or maybe we should leave it to the String itself?
+
+ | UInfixE Exp Exp Exp -- ^ @{x + y}@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | ParensE Exp -- ^ @{ (e) }@
+ --
+ -- See "Language.Haskell.TH.Syntax#infix"
+ | LamE [Pat] Exp -- ^ @{ \ p1 p2 -> e }@
+ | LamCaseE [Match] -- ^ @{ \case m1; m2 }@
+ | TupE [Exp] -- ^ @{ (e1,e2) } @
+ | UnboxedTupE [Exp] -- ^ @{ (# e1,e2 #) } @
+ | CondE Exp Exp Exp -- ^ @{ if e1 then e2 else e3 }@
+ | MultiIfE [(Guard, Exp)] -- ^ @{ if | g1 -> e1 | g2 -> e2 }@
+ | LetE [Dec] Exp -- ^ @{ let x=e1; y=e2 in e3 }@
+ | CaseE Exp [Match] -- ^ @{ case e of m1; m2 }@
+ | DoE [Stmt] -- ^ @{ do { p <- e1; e2 } }@
+ | CompE [Stmt] -- ^ @{ [ (x,y) | x <- xs, y <- ys ] }@
+ --
+ -- The result expression of the comprehension is
+ -- the /last/ of the @'Stmt'@s, and should be a 'NoBindS'.
+ --
+ -- E.g. translation:
+ --
+ -- > [ f x | x <- xs ]
+ --
+ -- > CompE [BindS (VarP x) (VarE xs), NoBindS (AppE (VarE f) (VarE x))]
+
+ | ArithSeqE Range -- ^ @{ [ 1 ,2 .. 10 ] }@
+ | ListE [ Exp ] -- ^ @{ [1,2,3] }@
+ | SigE Exp Type -- ^ @{ e :: t }@
+ | RecConE Name [FieldExp] -- ^ @{ T { x = y, z = w } }@
+ | RecUpdE Exp [FieldExp] -- ^ @{ (f x) { z = w } }@
+ deriving( Show, Eq, Data, Typeable )
+
+type FieldExp = (Name,Exp)
+
+-- Omitted: implicit parameters
+
+data Body
+ = GuardedB [(Guard,Exp)] -- ^ @f p { | e1 = e2
+ -- | e3 = e4 }
+ -- where ds@
+ | NormalB Exp -- ^ @f p { = e } where ds@
+ deriving( Show, Eq, Data, Typeable )
+
+data Guard
+ = NormalG Exp -- ^ @f x { | odd x } = x@
+ | PatG [Stmt] -- ^ @f x { | Just y <- x, Just z <- y } = z@
+ deriving( Show, Eq, Data, Typeable )
+
+data Stmt
+ = BindS Pat Exp
+ | LetS [ Dec ]
+ | NoBindS Exp
+ | ParS [[Stmt]]
+ deriving( Show, Eq, Data, Typeable )
+
+data Range = FromR Exp | FromThenR Exp Exp
+ | FromToR Exp Exp | FromThenToR Exp Exp Exp
+ deriving( Show, Eq, Data, Typeable )
+
+data Dec
+ = FunD Name [Clause] -- ^ @{ f p1 p2 = b where decs }@
+ | ValD Pat Body [Dec] -- ^ @{ p = b where decs }@
+ | DataD Cxt Name [TyVarBndr]
+ [Con] [Name] -- ^ @{ data Cxt x => T x = A x | B (T x)
+ -- deriving (Z,W)}@
+ | NewtypeD Cxt Name [TyVarBndr]
+ Con [Name] -- ^ @{ newtype Cxt x => T x = A (B x)
+ -- deriving (Z,W)}@
+ | TySynD Name [TyVarBndr] Type -- ^ @{ type T x = (x,x) }@
+ | ClassD Cxt Name [TyVarBndr]
+ [FunDep] [Dec] -- ^ @{ class Eq a => Ord a where ds }@
+ | InstanceD Cxt Type [Dec] -- ^ @{ instance Show w => Show [w]
+ -- where ds }@
+ | SigD Name Type -- ^ @{ length :: [a] -> Int }@
+ | ForeignD Foreign -- ^ @{ foreign import ... }
+ --{ foreign export ... }@
+
+ | InfixD Fixity Name -- ^ @{ infix 3 foo }@
+
+ -- | pragmas
+ | PragmaD Pragma -- ^ @{ {\-# INLINE [1] foo #-\} }@
+
+ -- | type families (may also appear in [Dec] of 'ClassD' and 'InstanceD')
+ | FamilyD FamFlavour Name
+ [TyVarBndr] (Maybe Kind) -- ^ @{ type family T a b c :: * }@
+
+ | DataInstD Cxt Name [Type]
+ [Con] [Name] -- ^ @{ data instance Cxt x => T [x] = A x
+ -- | B (T x)
+ -- deriving (Z,W)}@
+ | NewtypeInstD Cxt Name [Type]
+ Con [Name] -- ^ @{ newtype instance Cxt x => T [x] = A (B x)
+ -- deriving (Z,W)}@
+ | TySynInstD Name TySynEqn -- ^ @{ type instance ... }@
+
+ | ClosedTypeFamilyD Name
+ [TyVarBndr] (Maybe Kind)
+ [TySynEqn] -- ^ @{ type family F a b :: * where ... }@
+
+ | RoleAnnotD Name [Role] -- ^ @{ type role T nominal representational }@
+ deriving( Show, Eq, Data, Typeable )
+
+-- | One equation of a type family instance or closed type family. The
+-- arguments are the left-hand-side type patterns and the right-hand-side
+-- result.
+data TySynEqn = TySynEqn [Type] Type
+ deriving( Show, Eq, Data, Typeable )
+
+data FunDep = FunDep [Name] [Name]
+ deriving( Show, Eq, Data, Typeable )
+
+data FamFlavour = TypeFam | DataFam
+ deriving( Show, Eq, Data, Typeable )
+
+data Foreign = ImportF Callconv Safety String Name Type
+ | ExportF Callconv String Name Type
+ deriving( Show, Eq, Data, Typeable )
+
+data Callconv = CCall | StdCall
+ deriving( Show, Eq, Data, Typeable )
+
+data Safety = Unsafe | Safe | Interruptible
+ deriving( Show, Eq, Data, Typeable )
+
+data Pragma = InlineP Name Inline RuleMatch Phases
+ | SpecialiseP Name Type (Maybe Inline) Phases
+ | SpecialiseInstP Type
+ | RuleP String [RuleBndr] Exp Exp Phases
+ | AnnP AnnTarget Exp
+ deriving( Show, Eq, Data, Typeable )
+
+data Inline = NoInline
+ | Inline
+ | Inlinable
+ deriving (Show, Eq, Data, Typeable)
+
+data RuleMatch = ConLike
+ | FunLike
+ deriving (Show, Eq, Data, Typeable)
+
+data Phases = AllPhases
+ | FromPhase Int
+ | BeforePhase Int
+ deriving (Show, Eq, Data, Typeable)
+
+data RuleBndr = RuleVar Name
+ | TypedRuleVar Name Type
+ deriving (Show, Eq, Data, Typeable)
+
+data AnnTarget = ModuleAnnotation
+ | TypeAnnotation Name
+ | ValueAnnotation Name
+ deriving (Show, Eq, Data, Typeable)
+
+type Cxt = [Pred] -- ^ @(Eq a, Ord b)@
+
+-- | Since the advent of @ConstraintKinds@, constraints are really just types.
+-- Equality constraints use the 'EqualityT' constructor. Constraints may also
+-- be tuples of other constraints.
+type Pred = Type
+
+data Strict = IsStrict | NotStrict | Unpacked
+ deriving( Show, Eq, Data, Typeable )
+
+data Con = NormalC Name [StrictType] -- ^ @C Int a@
+ | RecC Name [VarStrictType] -- ^ @C { v :: Int, w :: a }@
+ | InfixC StrictType Name StrictType -- ^ @Int :+ a@
+ | ForallC [TyVarBndr] Cxt Con -- ^ @forall a. Eq a => C [a]@
+ deriving( Show, Eq, Data, Typeable )
+
+type StrictType = (Strict, Type)
+type VarStrictType = (Name, Strict, Type)
+
+data Type = ForallT [TyVarBndr] Cxt Type -- ^ @forall \<vars\>. \<ctxt\> -> \<type\>@
+ | AppT Type Type -- ^ @T a b@
+ | SigT Type Kind -- ^ @t :: k@
+ | VarT Name -- ^ @a@
+ | ConT Name -- ^ @T@
+ | PromotedT Name -- ^ @'T@
+
+ -- See Note [Representing concrete syntax in types]
+ | TupleT Int -- ^ @(,), (,,), etc.@
+ | UnboxedTupleT Int -- ^ @(#,#), (#,,#), etc.@
+ | ArrowT -- ^ @->@
+ | EqualityT -- ^ @~@
+ | ListT -- ^ @[]@
+ | PromotedTupleT Int -- ^ @'(), '(,), '(,,), etc.@
+ | PromotedNilT -- ^ @'[]@
+ | PromotedConsT -- ^ @(':)@
+ | StarT -- ^ @*@
+ | ConstraintT -- ^ @Constraint@
+ | LitT TyLit -- ^ @0,1,2, etc.@
+ deriving( Show, Eq, Data, Typeable )
+
+data TyVarBndr = PlainTV Name -- ^ @a@
+ | KindedTV Name Kind -- ^ @(a :: k)@
+ deriving( Show, Eq, Data, Typeable )
+
+data TyLit = NumTyLit Integer -- ^ @2@
+ | StrTyLit String -- ^ @"Hello"@
+ deriving ( Show, Eq, Data, Typeable )
+
+-- | Role annotations
+data Role = NominalR -- ^ @nominal@
+ | RepresentationalR -- ^ @representational@
+ | PhantomR -- ^ @phantom@
+ | InferR -- ^ @_@
+ deriving( Show, Eq, Data, Typeable )
+
+-- | Annotation target for reifyAnnotations
+data AnnLookup = AnnLookupModule Module
+ | AnnLookupName Name
+ deriving( Show, Eq, Data, Typeable )
+
+-- | To avoid duplication between kinds and types, they
+-- are defined to be the same. Naturally, you would never
+-- have a type be 'StarT' and you would never have a kind
+-- be 'SigT', but many of the other constructors are shared.
+-- Note that the kind @Bool@ is denoted with 'ConT', not
+-- 'PromotedT'. Similarly, tuple kinds are made with 'TupleT',
+-- not 'PromotedTupleT'.
+
+type Kind = Type
+
+{- Note [Representing concrete syntax in types]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Haskell has a rich concrete syntax for types, including
+ t1 -> t2, (t1,t2), [t], and so on
+In TH we represent all of this using AppT, with a distinguished
+type constructor at the head. So,
+ Type TH representation
+ -----------------------------------------------
+ t1 -> t2 ArrowT `AppT` t2 `AppT` t2
+ [t] ListT `AppT` t
+ (t1,t2) TupleT 2 `AppT` t1 `AppT` t2
+ '(t1,t2) PromotedTupleT 2 `AppT` t1 `AppT` t2
+
+But if the original HsSyn used prefix application, we won't use
+these special TH constructors. For example
+ [] t ConT "[]" `AppT` t
+ (->) t ConT "->" `AppT` t
+In this way we can faithfully represent in TH whether the original
+HsType used concrete syntax or not.
+
+The one case that doesn't fit this pattern is that of promoted lists
+ '[ Maybe, IO ] PromotedListT 2 `AppT` t1 `AppT` t2
+but it's very smelly because there really is no type constructor
+corresponding to PromotedListT. So we encode HsExplicitListTy with
+PromotedConsT and PromotedNilT (which *do* have underlying type
+constructors):
+ '[ Maybe, IO ] PromotedConsT `AppT` Maybe `AppT`
+ (PromotedConsT `AppT` IO `AppT` PromotedNilT)
+-}
+
+-----------------------------------------------------
+-- Internal helper functions
+-----------------------------------------------------
+
+cmpEq :: Ordering -> Bool
+cmpEq EQ = True
+cmpEq _ = False
+
+thenCmp :: Ordering -> Ordering -> Ordering
+thenCmp EQ o2 = o2
+thenCmp o1 _ = o1