Revision 53664e15

b/htools/Ganeti/THH.hs
43 43

  
44 44
import qualified Text.JSON as JSON
45 45

  
46
-- * Helper functions
47

  
46 48
-- | Ensure first letter is lowercase.
47 49
--
48 50
-- Used to convert type name to function prefix, e.g. in @data Aa ->
......
51 53
ensureLower [] = []
52 54
ensureLower (x:xs) = toLower x:xs
53 55

  
56
-- | Helper for quoted expressions.
57
varNameE :: String -> Q Exp
58
varNameE = varE . mkName
59

  
60
-- | showJSON as an expression, for reuse.
61
showJSONE :: Q Exp
62
showJSONE = varNameE "showJSON"
63

  
54 64
-- | ToString function name.
55 65
toStrName :: String -> Name
56 66
toStrName = mkName . (++ "ToString") . ensureLower
......
62 72
-- | Converts a name to it's varE/litE representations.
63 73
--
64 74
reprE :: Either String Name -> Q Exp
65
reprE (Left name) = litE (StringL name)
66
reprE (Right name) = varE name
75
reprE = either stringE varE
76

  
77
-- * Template code for simple string-equivalent ADTs
67 78

  
68 79
-- | Generates a data type declaration.
69 80
--
......
183 194
               JSON.Ok s' -> $(varE (fromStrName name)) s'
184 195
               JSON.Error e ->
185 196
                   JSON.Error $ "Can't parse string value for type " ++
186
                           $(litE (StringL name)) ++ ": " ++ e
197
                           $(stringE name) ++ ": " ++ e
187 198
           |]
188 199
  return $ FunD (mkName "readJSON") [Clause [VarP s] (NormalB body) []]
189 200

  
......
198 209
  readJ <- genReadJSON base
199 210
  return [InstanceD [] (AppT (ConT ''JSON.JSON) (ConT name)) (readJ:showJ)]
200 211

  
212
-- * Template code for opcodes
213

  
201 214
-- | Transforms a CamelCase string into an_underscore_based_one.
202 215
deCamelCase :: String -> String
203 216
deCamelCase =
......
282 295
          -> Q Exp
283 296
saveField fvar (fname, qt, _) = do
284 297
  t <- qt
285
  let showJ = varE (mkName "showJSON")
286
      fnexp = litE (stringL fname)
298
  let fnexp = stringE fname
287 299
      fvare = varE fvar
288 300
  (if isOptional t
289 301
   then [| case $fvare of
290
             Just v' -> [( $fnexp, $showJ v')]
302
             Just v' -> [( $fnexp, $showJSONE v')]
291 303
             Nothing -> []
292 304
         |]
293
   else [| [( $fnexp, $showJ $fvare )] |])
305
   else [| [( $fnexp, $showJSONE $fvare )] |])
294 306

  
295 307
-- | Generates the \"save\" clause for an entire opcode constructor.
296 308
--
......
307 319
  let pat = conP cname (map varP fnames)
308 320
  let felems = map (uncurry saveField) (zip fnames fields)
309 321
      -- now build the OP_ID serialisation
310
      opid = [| [( $(litE (stringL "OP_ID")),
311
                   $(varE (mkName "showJSON"))
312
                        $(litE . stringL . deCamelCase $ sname) )] |]
322
      opid = [| [( $(stringE "OP_ID"),
323
                   $showJSONE $(stringE . deCamelCase $ sname) )] |]
313 324
      flist = listE (opid:felems)
314 325
      -- and finally convert all this to a json object
315
      flist' = [| $(varE (mkName "makeObj")) (concat $flist) |]
326
      flist' = [| $(varNameE "makeObj") (concat $flist) |]
316 327
  clause [pat] (normalB flist') []
317 328

  
318 329
-- | Generates the main save opcode function.
......
339 350
  t <- qt
340 351
  defa <- qdefa
341 352
  -- these are used in all patterns below
342
  let objvar = varE (mkName "o")
343
      objfield = litE (StringL fname)
353
  let objvar = varNameE "o"
354
      objfield = stringE fname
344 355
  bexp <- if isOptional t
345
          then [| $((varE (mkName "maybeFromObj"))) $objvar $objfield |]
356
          then [| $((varNameE "maybeFromObj")) $objvar $objfield |]
346 357
          else case defa of
347 358
                 AppE (ConE dt) defval | dt == 'Just ->
348 359
                   -- but has a default value
349
                   [| $(varE (mkName "fromObjWithDefault"))
360
                   [| $(varNameE "fromObjWithDefault")
350 361
                      $objvar $objfield $(return defval) |]
351 362
                 ConE dt | dt == 'Nothing ->
352
                     [| $(varE (mkName "fromObj")) $objvar $objfield |]
363
                     [| $(varNameE "fromObj") $objvar $objfield |]
353 364
                 s -> fail $ "Invalid default value " ++ show s ++
354 365
                      ", expecting either 'Nothing' or a 'Just defval'"
355 366
  return (fvar, BindS (VarP fvar) bexp)
......
371 382
      opid = mkName "op_id"
372 383
  st1 <- bindS (varP objname) [| liftM JSON.fromJSObject
373 384
                                 (JSON.readJSON $(varE arg1)) |]
374
  st2 <- bindS (varP opid) [| $(varE (mkName "fromObj"))
375
                              $(varE objname) $(litE (stringL "OP_ID")) |]
385
  st2 <- bindS (varP opid) [| $(varNameE "fromObj")
386
                              $(varE objname) $(stringE "OP_ID") |]
376 387
  -- the match results (per-constructor blocks)
377 388
  mexps <- mapM (uncurry loadConstructor) opdefs
378 389
  fails <- [| fail $ "Unknown opcode " ++ $(varE opid) |]

Also available in: Unified diff