Documentation for Language.Haskell.TH.Quote.
[ghc.git] / libraries / template-haskell / Language / Haskell / TH / Quote.hs
1 {-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
2 {- |
3 Module : Language.Haskell.TH.Quote
4 Description : Quasi-quoting support for Template Haskell
5
6 Template Haskell supports quasiquoting, which permits users to construct
7 program fragments by directly writing concrete syntax. A quasiquoter is
8 essentially a function with takes a string to a Template Haskell AST.
9 This module defines the 'QuasiQuoter' datatype, which specifies a
10 quasiquoter @q@ which can be invoked using the syntax
11 @[q| ... string to parse ... |]@ when the @QuasiQuotes@ language
12 extension is enabled, and some utility functions for manipulating
13 quasiquoters. Nota bene: this package does not define any parsers,
14 that is up to you.
15 -}
16 module Language.Haskell.TH.Quote(
17 QuasiQuoter(..),
18 dataToQa, dataToExpQ, dataToPatQ,
19 quoteFile
20 ) where
21
22 import Data.Data
23 import Language.Haskell.TH.Lib
24 import Language.Haskell.TH.Syntax
25
26 -- | The 'QuasiQuoter' type, a value @q@ of this type can be used
27 -- in the syntax @[q| ... string to parse ...|]@. In fact, for
28 -- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
29 -- to be used in different splice contexts; if you are only interested
30 -- in defining a quasiquoter to be used for expressions, you would
31 -- define a 'QuasiQuoter' with only 'quoteExp', and leave the other
32 -- fields stubbed out with errors.
33 data QuasiQuoter = QuasiQuoter {
34 -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
35 quoteExp :: String -> Q Exp,
36 -- | Quasi-quoter for patterns, invoked by quotes like @f $[q|...] = rhs@
37 quotePat :: String -> Q Pat,
38 -- | Quasi-quoter for types, invoked by quotes like @f :: $[q|...]@
39 quoteType :: String -> Q Type,
40 -- | Quasi-quoter for declarations, invoked by top-level quotes
41 quoteDec :: String -> Q [Dec]
42 }
43
44 -- | 'dataToQa' is a generic utility function for constructing generic
45 -- conversion functions from types with 'Data' instances to various
46 -- quasi-quoting representations. It's used by 'dataToExpQ' and
47 -- 'dataToPatQ'
48 dataToQa :: forall a k q. Data a
49 => (Name -> k)
50 -> (Lit -> Q q)
51 -> (k -> [Q q] -> Q q)
52 -> (forall b . Data b => b -> Maybe (Q q))
53 -> a
54 -> Q q
55 dataToQa mkCon mkLit appCon antiQ t =
56 case antiQ t of
57 Nothing ->
58 case constrRep constr of
59 AlgConstr _ ->
60 appCon (mkCon conName) conArgs
61 where
62 conName :: Name
63 conName =
64 case showConstr constr of
65 "(:)" -> Name (mkOccName ":") (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Types"))
66 con@"[]" -> Name (mkOccName con) (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Types"))
67 con@('(':_) -> Name (mkOccName con) (NameG DataName (mkPkgName "ghc-prim") (mkModName "GHC.Tuple"))
68 con -> mkNameG_d (tyConPackage tycon)
69 (tyConModule tycon)
70 con
71 where
72 tycon :: TyCon
73 tycon = (typeRepTyCon . typeOf) t
74
75 conArgs :: [Q q]
76 conArgs = gmapQ (dataToQa mkCon mkLit appCon antiQ) t
77 IntConstr n ->
78 mkLit $ integerL n
79 FloatConstr n ->
80 mkLit $ rationalL n
81 CharConstr c ->
82 mkLit $ charL c
83 where
84 constr :: Constr
85 constr = toConstr t
86
87 Just y -> y
88
89 -- | 'dataToExpQ' converts a value to a 'Q Exp' representation of the
90 -- same value, in the SYB style. It is generalized to take a function
91 -- override type-specific cases; a useful default is 'const Nothing'
92 -- for no overriding.
93 dataToExpQ :: Data a
94 => (forall b . Data b => b -> Maybe (Q Exp))
95 -> a
96 -> Q Exp
97 dataToExpQ = dataToQa conE litE (foldl appE)
98
99 -- | 'dataToPatQ' converts a value to a 'Q Pat' representation of the same
100 -- value, in the SYB style. It takes a function to handle type-specific cases,
101 -- alternatively, pass @const Nothing@ to get default behavior.
102 dataToPatQ :: Data a
103 => (forall b . Data b => b -> Maybe (Q Pat))
104 -> a
105 -> Q Pat
106 dataToPatQ = dataToQa id litP conP
107
108 -- | 'quoteFile' takes a 'QuasiQuoter' and lifts it into one that read
109 -- the data out of a file. For example, suppose 'asmq' is an
110 -- assembly-language quoter, so that you can write [asmq| ld r1, r2 |]
111 -- as an expression. Then if you define @asmq_f = quoteFile asmq@, then
112 -- the quote [asmq_f|foo.s|] will take input from file @"foo.s"@ instead
113 -- of the inline text
114 quoteFile :: QuasiQuoter -> QuasiQuoter
115 quoteFile (QuasiQuoter { quoteExp = qe, quotePat = qp, quoteType = qt, quoteDec = qd })
116 = QuasiQuoter { quoteExp = get qe, quotePat = get qp, quoteType = get qt, quoteDec = get qd }
117 where
118 get :: (String -> Q a) -> String -> Q a
119 get old_quoter file_name = do { file_cts <- runIO (readFile file_name)
120 ; addDependentFile file_name
121 ; old_quoter file_cts }