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