Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
-- 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
import Control.Monad( liftM, liftM2 )
----------------------------------------------------------
-- Type synonyms
----------------------------------------------------------
type InfoQ = Q Info
type ExpQ = Q Exp
type DecQ = Q Dec
type ConQ = Q Con
type TypeQ = Q Type
type CxtQ = Q Cxt
type MatchQ = Q Match
type ClauseQ = Q Clause
type BodyQ = Q Body
type StmtQ = Q Stmt
type RangeQ = Q Range
type StrictTypeQ = Q StrictType
type VarStrictTypeQ = Q VarStrictType
----------------------------------------------------------
-- Lowercase pattern syntax functions
----------------------------------------------------------
intPrimL :: Integer -> Lit
intPrimL = IntPrimL
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
rationalL :: Rational -> Lit
rationalL = RationalL
litP :: Lit -> Pat
litP = LitP
varP :: Name -> Pat
varP = VarP
tupP :: [Pat] -> Pat
tupP = TupP
conP :: Name -> [Pat] -> Pat
conP = ConP
tildeP :: Pat -> Pat
tildeP = TildeP
asP :: Name -> Pat -> Pat
asP = AsP
wildP :: Pat
wildP = WildP
recP :: Name -> [FieldPat] -> Pat
recP = RecP
listP :: [Pat] -> Pat
listP = ListP
fieldPat :: Name -> Pat -> (Name, Pat)
fieldPat = (,)
-------------------------------------------------------------------------------
-- Stmt
bindS :: Pat -> ExpQ -> StmtQ
bindS p e = liftM (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 _ = fail "No parallel comprehensions yet"
-------------------------------------------------------------------------------
-- 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 :: [(ExpQ,ExpQ)] -> BodyQ
guardedB ges = do { ges' <- mapM f ges; return (GuardedB ges') }
where f (g, e) = do { g' <- g; e' <- e; return (g', e') }
-------------------------------------------------------------------------------
-- Match and Clause
match :: Pat -> BodyQ -> [DecQ] -> MatchQ
match p rhs ds = do { r' <- rhs;
ds' <- sequence ds;
return (Match p r' ds') }
clause :: [Pat] -> BodyQ -> [DecQ] -> ClauseQ
clause ps r ds = do { r' <- r;
ds' <- sequence ds;
return (Clause ps r' ds') }
---------------------------------------------------------------------------
-- Exp
global :: Name -> ExpQ
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)}
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 :: [Pat] -> ExpQ -> ExpQ
lamE ps e = liftM (LamE ps) e
lam1E :: Pat -> ExpQ -> ExpQ -- Single-arg lambda
lam1E p e = lamE [p] e
tupE :: [ExpQ] -> ExpQ
tupE es = do { es1 <- sequence es; return (TupE es1)}
condE :: ExpQ -> ExpQ -> ExpQ -> ExpQ
condE x y z = do { a <- x; b <- y; c <- z; return (CondE a b c)}
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') }
-- 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)) }
-- End arithSeqE shortcuts
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') }
-------------------------------------------------------------------------------
-- Dec
valD :: Pat -> BodyQ -> [DecQ] -> DecQ
valD p b ds =
do { 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 -> [Name] -> TypeQ -> DecQ
tySynD tc tvs rhs = do { rhs1 <- rhs; return (TySynD tc tvs rhs1) }
dataD :: CxtQ -> Name -> [Name] -> [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 -> [Name] -> ConQ -> [Name] -> DecQ
newtypeD ctxt tc tvs con derivs =
do
ctxt1 <- ctxt
con1 <- con
return (NewtypeD ctxt1 tc tvs con1 derivs)
classD :: CxtQ -> Name -> [Name] -> [DecQ] -> DecQ
classD ctxt cls tvs decs =
do
decs1 <- sequence decs
ctxt1 <- ctxt
return $ ClassD ctxt1 cls tvs 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
cxt :: [TypeQ] -> 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'
-------------------------------------------------------------------------------
-- Type
forallT :: [Name] -> 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
tupleT :: Int -> TypeQ
tupleT i = return (TupleT i)
isStrict, notStrict :: Q Strict
isStrict = return $ IsStrict
notStrict = return $ NotStrict
strictType :: Q Strict -> TypeQ -> StrictTypeQ
strictType = liftM2 (,)
varStrictType :: Name -> StrictTypeQ -> VarStrictTypeQ
varStrictType v st = do (s, t) <- st
return (v, s, t)
--------------------------------------------------------------
-- Useful helper functions
combine :: [([(Name, Name)], Pat)] -> ([(Name, Name)], [Pat])
combine pairs = foldr f ([],[]) pairs
where f (env,p) (es,ps) = (env++es,p:ps)
rename :: Pat -> Q ([(Name, Name)], Pat)
rename (LitP c) = return([],LitP c)
rename (VarP s) = do { s1 <- newName (nameBase s); return([(s,s1)],VarP s1) }
rename (TupP pats) = do { pairs <- mapM rename pats; g(combine pairs) }
where g (es,ps) = return (es,TupP ps)
rename (ConP nm pats) = do { pairs <- mapM rename pats; g(combine pairs) }
where g (es,ps) = return (es,ConP nm ps)
rename (TildeP p) = do { (env,p2) <- rename p; return(env,TildeP p2) }
rename (AsP s p) =
do { s1 <- newName (nameBase s); (env,p2) <- rename p; return((s,s1):env,AsP s1 p2) }
rename WildP = return([],WildP)
rename (RecP nm fs) = do { pairs <- mapM rename ps; g(combine pairs) }
where g (env,ps') = return (env,RecP nm (zip ss ps'))
(ss,ps) = unzip fs
rename (ListP pats) = do { pairs <- mapM rename pats; g(combine pairs) }
where g (es,ps) = return (es,ListP ps)
genpat :: Pat -> Q ((Name -> ExpQ), Pat)
genpat p = do { (env,p2) <- rename p; return (alpha env,p2) }
alpha :: [(Name, Name)] -> Name -> ExpQ
alpha env s = case lookup s env of
Just x -> varE x
Nothing -> varE s
appsE :: [ExpQ] -> ExpQ
appsE [] = error "appsExp []"
appsE [x] = x
appsE (x:y:zs) = appsE ( (appE x y) : zs )
simpleMatch :: Pat -> Exp -> Match
simpleMatch p e = Match p (NormalB e) []