Revision b20cbf06 htools/Ganeti/THH.hs

b/htools/Ganeti/THH.hs
29 29

  
30 30
-}
31 31

  
32
module Ganeti.THH ( Store(..)
33
                  , declareSADT
32
module Ganeti.THH ( declareSADT
34 33
                  , makeJSONInstance
35 34
                  , genOpID
36 35
                  , genOpCode
......
429 428
-- | LuxiOp parameter type.
430 429
type LuxiParam = (String, Q Type, Q Exp)
431 430

  
432
-- | Storage options for JSON.
433
data Store = SList | SDict
434

  
435 431
-- | Generates the LuxiOp data type.
436 432
--
437 433
-- This takes a Luxi operation definition and builds both the
......
448 444
-- * operation; this is the operation performed on the parameter before
449 445
--   serialization
450 446
--
451
genLuxiOp :: String -> [(String, [LuxiParam], Store)] -> Q [Dec]
447
genLuxiOp :: String -> [(String, [LuxiParam])] -> Q [Dec]
452 448
genLuxiOp name cons = do
453
  decl_d <- mapM (\(cname, fields, _) -> do
449
  decl_d <- mapM (\(cname, fields) -> do
454 450
                    fields' <- mapM (\(_, qt, _) ->
455 451
                                         qt >>= \t -> return (NotStrict, t))
456 452
                               fields
......
460 456
  (savesig, savefn) <- genSaveLuxiOp cons
461 457
  return [declD, savesig, savefn]
462 458

  
463
-- | Generates a Q Exp for an element, depending of the JSON return type.
464
helperLuxiField :: Store -> String -> Q Exp -> Q Exp
465
helperLuxiField SList name val = [| [ JSON.showJSON $val ] |]
466
helperLuxiField SDict name val = [| [(name, JSON.showJSON $val)] |]
467

  
468 459
-- | Generates the \"save\" expression for a single luxi parameter.
469
saveLuxiField :: Store -> Name -> LuxiParam -> Q Exp
470
saveLuxiField store fvar (fname, qt, fn) = do
471
  t <- qt
472
  let fvare = varE fvar
473
  (if isOptional t
474
   then [| case $fvare of
475
             Just v' ->
476
                 $(helperLuxiField store fname $ liftM2 appFn fn [| v' |])
477
             Nothing -> []
478
         |]
479
   else helperLuxiField store fname $ liftM2 appFn fn fvare)
480

  
481
-- | Generates final JSON Q Exp for constructor.
482
helperLuxiConstructor :: Store -> Q Exp -> Q Exp
483
helperLuxiConstructor SDict val = [| JSON.showJSON $ JSON.makeObj $val |]
484
helperLuxiConstructor SList val = [| JSON.JSArray $val |]
460
saveLuxiField :: Name -> LuxiParam -> Q Exp
461
saveLuxiField fvar (_, qt, fn) =
462
    [| JSON.showJSON ( $(liftM2 appFn fn $ varE fvar) ) |]
485 463

  
486 464
-- | Generates the \"save\" clause for entire LuxiOp constructor.
487
saveLuxiConstructor :: (String, [LuxiParam], Store) -> Q Clause
488
saveLuxiConstructor (sname, fields, store) = do
465
saveLuxiConstructor :: (String, [LuxiParam]) -> Q Clause
466
saveLuxiConstructor (sname, fields) = do
489 467
  let cname = mkName sname
490 468
      fnames = map (\(nm, _, _) -> mkName nm) fields
491 469
      pat = conP cname (map varP fnames)
492
      flist = map (uncurry $ saveLuxiField store) (zip fnames fields)
493
      flist' = appE [| concat |] (listE flist)
494
      finval = helperLuxiConstructor store flist'
470
      flist = map (uncurry saveLuxiField) (zip fnames fields)
471
      finval = if null flist
472
               then [| JSON.showJSON ()    |]
473
               else [| JSON.showJSON $(listE flist) |]
495 474
  clause [pat] (normalB finval) []
496 475

  
497 476
-- | Generates the main save LuxiOp function.
498
genSaveLuxiOp :: [(String, [LuxiParam], Store)]-> Q (Dec, Dec)
477
genSaveLuxiOp :: [(String, [LuxiParam])]-> Q (Dec, Dec)
499 478
genSaveLuxiOp opdefs = do
500 479
  sigt <- [t| $(conT (mkName "LuxiOp")) -> JSON.JSValue |]
501 480
  let fname = mkName "opToArgs"

Also available in: Unified diff