Revision 260d0bda htools/Ganeti/THH.hs

b/htools/Ganeti/THH.hs
30 30
-}
31 31

  
32 32
module Ganeti.THH ( declareSADT
33
                  , declareIADT
33 34
                  , makeJSONInstance
35
                  , makeJSONInstanceInt
34 36
                  , genOpID
35 37
                  , genOpCode
36 38
                  , noDefault
......
68 70
toStrName :: String -> Name
69 71
toStrName = mkName . (++ "ToString") . ensureLower
70 72

  
73
-- | ToInt function name.
74
toIntName :: String -> Name
75
toIntName= mkName . (++ "ToInt") . ensureLower
76

  
71 77
-- | FromString function name.
72 78
fromStrName :: String -> Name
73 79
fromStrName = mkName . (++ "FromString") . ensureLower
74 80

  
81
-- | FromInt function name.
82
fromIntName:: String -> Name
83
fromIntName = mkName . (++ "FromInt") . ensureLower
84

  
75 85
-- | Converts a name to it's varE/litE representations.
76 86
--
77 87
reprE :: Either String Name -> Q Exp
......
85 95
appFn f x | f == VarE 'id = x
86 96
          | otherwise = AppE f x
87 97

  
98
-- * Template code for simple integer-equivalent ADTs
99

  
100
-- | Generates a data type declaration.
101
--
102
-- The type will have a fixed list of instances.
103
intADTDecl :: Name -> [String] -> Dec
104
intADTDecl name constructors =
105
    DataD [] name []
106
              (map (flip NormalC [] . mkName) constructors)
107
              [''Show]
108

  
109
-- | Generates a toInt function.
110
genToInt :: Name -> Name -> [(String, Name)] -> Q [Dec]
111
genToInt fname tname constructors = do
112
  sigt <- [t| $(conT tname) -> Int |]
113
  clauses <- mapM  (\(c, v) -> clause [recP (mkName c) []]
114
                             (normalB (varE v)) []) constructors
115
  return [SigD fname sigt, FunD fname clauses]
116

  
117
-- | Generates a fromInt function.
118
genFromInt :: Name -> Name -> [(String, Name)] -> Q [Dec]
119
genFromInt fname tname constructors = do
120
  sigt <- [t| (Monad m) => Int-> m $(conT tname) |]
121
  let varp = mkName "s"
122
      varpe = varE varp
123
  clauses <- mapM (\(c, v) -> do
124
                     g <- normalG [| $varpe == $(varE v) |]
125
                     r <- [| return $(conE (mkName c)) |]
126
                     return (g, r)) constructors
127
  oth_clause <- do
128
    g <- normalG [| otherwise |]
129
    r <- [|fail ("Invalid int value for type " ++
130
                 $(litE (stringL (nameBase tname))) ++ ": " ++ show $varpe) |]
131
    return (g, r)
132
  let fun = FunD fname [Clause [VarP varp]
133
                        (GuardedB (clauses++[oth_clause])) []]
134
  return [SigD fname sigt, fun]
135

  
136
-- | Generates a data type from a given string format.
137
declareIADT:: String -> [(String, Name)] -> Q [Dec]
138
declareIADT sname cons = do
139
  let name = mkName sname
140
      ddecl = intADTDecl name (map fst cons)
141
  tostr <- genToInt (toIntName sname) name cons
142
  fromstr <- genFromInt (fromIntName sname) name cons
143
  return $ ddecl:tostr ++ fromstr
144

  
145
-- | Creates the showJSON member of a JSON instance declaration.
146
genShowJSONInt :: String -> Q [Dec]
147
genShowJSONInt name = [d| showJSON = JSON.showJSON . $(varE (toIntName name)) |]
148

  
149
-- | Creates the readJSON member of a JSON instance declaration.
150
genReadJSONInt :: String -> Q Dec
151
genReadJSONInt name = do
152
  let s = mkName "s"
153
  body <- [| case JSON.readJSON $(varE s) of
154
               JSON.Ok s' -> $(varE (fromIntName name)) s'
155
               JSON.Error e ->
156
                   JSON.Error $ "Can't parse int value for type " ++
157
                           $(stringE name) ++ ": " ++ e
158
           |]
159
  return $ FunD (mkName "readJSON") [Clause [VarP s] (NormalB body) []]
160

  
161
-- | Generates a JSON instance for a given type.
162
makeJSONInstanceInt :: Name -> Q [Dec]
163
makeJSONInstanceInt name = do
164
  let base = nameBase name
165
  showJ <- genShowJSONInt base
166
  readJ <- genReadJSONInt base
167
  return [InstanceD [] (AppT (ConT ''JSON.JSON) (ConT name)) (readJ:showJ)]
168

  
88 169
-- * Template code for simple string-equivalent ADTs
89 170

  
90 171
-- | Generates a data type declaration.

Also available in: Unified diff