Revision 92678b3c htools/Ganeti/THH.hs

b/htools/Ganeti/THH.hs
29 29

  
30 30
-}
31 31

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

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

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

  
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
-- | 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 |]
485

  
459 486
-- | Generates the \"save\" clause for entire LuxiOp constructor.
460
saveLuxiConstructor :: (String, [LuxiParam]) -> Q Clause
461
saveLuxiConstructor (sname, fields) =
487
saveLuxiConstructor :: (String, [LuxiParam], Store) -> Q Clause
488
saveLuxiConstructor (sname, fields, store) = do
462 489
  let cname = mkName sname
463 490
      fnames = map (\(nm, _, _) -> mkName nm) fields
464 491
      pat = conP cname (map varP fnames)
465
      flist = map (\(nm, _, fn) -> liftM2 appFn fn $ (varNameE nm)) fields
466
      showlist = map (\x -> [| JSON.showJSON $x |]) flist
467
      finval = case showlist of
468
                 [] -> [| JSON.showJSON () |]
469
                 _ -> [| JSON.showJSON $(listE showlist) |]
470
  in clause [pat] (normalB finval) []
492
      flist = map (uncurry $ saveLuxiField store) (zip fnames fields)
493
      flist' = appE [| concat |] (listE flist)
494
      finval = helperLuxiConstructor store flist'
495
  clause [pat] (normalB finval) []
471 496

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

Also available in: Unified diff