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
|
module Database.HaskellDB.TH where
import Control.Monad
import Database.HaskellDB.DBLayout
import Language.Haskell.TH
table :: String
-> String
-> [Name]
-> Q [Dec]
table name schemaname fields = do
body <- [| baseTable $(nameString) $(expand fields) |]
typ <- genSig fields
return [sig typ,def body]
where nameString = return $ LitE $ StringL schemaname
sig typ = SigD tableName typ
def body = ValD (VarP tableName) (NormalB body) []
tableName = mkName name
expand [] = error "expand"
expand (name:fields) = do
(info,typ) <- nameAndTyp name
let expr = getCons typ
case fields of
[] -> [| hdbMakeEntry $(return expr) |]
fields -> [| hdbMakeEntry $(return expr) # $(expand fields) |]
getCons (TyConI (DataD _ _ _ [NormalC typ _] _)) = ConE typ
getCons _ = error "getCons"
genSig :: [Name] -> Q Type
genSig fields = [t| Table $(foldM cons nil (reverse fields)) |]
where cons acc name = do
(info,typ) <- nameAndTyp name
[t| RecCons $(getConsT typ) (Expr $(getFundType info)) $(return acc) |]
getConsT (TyConI (DataD _ typ _ _ _)) = return $ ConT $ typ
getConsT _ = error "getConsT"
getFundType (VarI _var (getFundSubType -> cons) _ _) = return cons
getFundType _ = error "getFundType"
getFundSubType (AppT _ cons) = cons
getFundSubType _ = error "getFundSubType"
nil = ConT ''RecNil
nameAndTyp :: Name -> Q (Info,Info)
nameAndTyp name = do
info <- reify name
typ <- reify (getTypeNameFromInfo info)
return (info,typ)
where getTypeNameFromInfo (VarI _var (getType -> cons) _ _) = cons
getTypeNameFromInfo _ = error "getTypeNameFromInfo"
getType (AppT (AppT _ (ConT cons)) _) = cons
getType _ = error "getType"
field :: String
-> String
-> String
-> TypeQ
-> Q [Dec]
field (mkName -> typeName) (mkName -> varName) colName colTypeQ = do
colType <- colTypeQ
return [dataDef,instanceDef,valSig colType,valDef] where
dataDef = DataD context typeName [] constructors derives
where constructors = [NormalC typeName []]
derives = []
instanceDef = InstanceD context (className `AppT` constrName) [method]
where className = con ''FieldTag
method = FunD 'fieldName [Clause [WildP] body typeAnn]
body = NormalB $ LitE $ StringL colName
valSig colType = SigD varName $ attrType `AppT` constrName `AppT` colType
where attrType = con ''Attr
valDef = VarP varName `ValD` body $ typeAnn
where body = NormalB $ VarE 'mkAttr `AppE` ConE typeName
constrName = con typeName
con = ConT
context = []
typeAnn = []
printQ :: (Ppr a) => Q a -> IO ()
printQ f = do
s <- runQ f
putStrLn $ pprint s
|