|
|
|
|
|
Description |
TemplateHaskell helper for HTools.
As TemplateHaskell require that splices be defined in a separate
module, we combine all the TemplateHaskell functionality that HTools
needs in this module (except the one for unittests).
|
|
Synopsis |
|
type Container = Map String | | data Field = Field {} | | simpleField :: String -> Q Type -> Field | | renameField :: String -> Field -> Field | | defaultField :: Q Exp -> Field -> Field | | optionalField :: Field -> Field | | containerField :: Field -> Field | | customField :: Name -> Name -> Field -> Field | | fieldRecordName :: Field -> String | | fieldVariable :: Field -> String | | actualFieldType :: Field -> Q Type | | checkNonOptDef :: Monad m => Field -> m () | | loadFn :: Field -> Q Exp -> Q Exp -> Q Exp | | timeStampFields :: [Field] | | serialFields :: [Field] | | uuidFields :: [Field] | | ensureLower :: String -> String | | ensureUpper :: String -> String | | varNameE :: String -> Q Exp | | showJSONE :: Q Exp | | toRawName :: String -> Name | | fromRawName :: String -> Name | | reprE :: Either String Name -> Q Exp | | appFn :: Exp -> Exp -> Exp | | readContainer :: (Monad m, JSON a) => JSObject JSValue -> m (Container a) | | showContainer :: JSON a => Container a -> JSValue | | strADTDecl :: Name -> [String] -> Dec | | genToRaw :: Name -> Name -> Name -> [(String, Either String Name)] -> Q [Dec] | | genFromRaw :: Name -> Name -> Name -> [(String, Name)] -> Q [Dec] | | declareADT :: Name -> String -> [(String, Name)] -> Q [Dec] | | declareIADT :: String -> [(String, Name)] -> Q [Dec] | | declareSADT :: String -> [(String, Name)] -> Q [Dec] | | genShowJSON :: String -> Q Dec | | genReadJSON :: String -> Q Dec | | makeJSONInstance :: Name -> Q [Dec] | | deCamelCase :: String -> String | | camelCase :: String -> String | | constructorName :: Con -> Q Name | | genConstrToStr :: (String -> String) -> Name -> String -> Q [Dec] | | genOpID :: Name -> String -> Q [Dec] | | type OpParam = (String, Q Type, Q Exp) | | genOpCode :: String -> [(String, [Field])] -> Q [Dec] | | isOptional :: Type -> Bool | | saveConstructor :: String -> [Field] -> Q Clause | | genSaveOpCode :: [(String, [Field])] -> Q (Dec, Dec) | | loadConstructor :: String -> [Field] -> Q Exp | | genLoadOpCode :: [(String, [Field])] -> Q (Dec, Dec) | | genStrOfOp :: Name -> String -> Q [Dec] | | genStrOfKey :: Name -> String -> Q [Dec] | | type LuxiParam = (String, Q Type, Q Exp) | | genLuxiOp :: String -> [(String, [LuxiParam])] -> Q [Dec] | | saveLuxiField :: Name -> LuxiParam -> Q Exp | | saveLuxiConstructor :: (String, [LuxiParam]) -> Q Clause | | genSaveLuxiOp :: [(String, [LuxiParam])] -> Q (Dec, Dec) | | fieldTypeInfo :: String -> Field -> Q (Name, Strict, Type) | | buildObject :: String -> String -> [Field] -> Q [Dec] | | buildObjectSerialisation :: String -> [Field] -> Q [Dec] | | genSaveObject :: (Name -> Field -> Q Exp) -> String -> [Field] -> Q [Dec] | | saveObjectField :: Name -> Field -> Q Exp | | objectShowJSON :: String -> Q Dec | | genLoadObject :: (Field -> Q (Name, Stmt)) -> String -> [Field] -> Q (Dec, Dec) | | loadObjectField :: Field -> Q (Name, Stmt) | | objectReadJSON :: String -> Q Dec | | paramTypeNames :: String -> (String, String) | | paramFieldTypeInfo :: String -> Field -> Q (Name, Strict, Type) | | buildParam :: String -> String -> [Field] -> Q [Dec] | | buildPParamSerialisation :: String -> [Field] -> Q [Dec] | | savePParamField :: Name -> Field -> Q Exp | | loadPParamField :: Field -> Q (Name, Stmt) | | buildFromMaybe :: String -> Q Dec | | fillParam :: String -> String -> [Field] -> Q [Dec] |
|
|
|
Exported types
|
|
type Container = Map String | Source |
|
|
|
Serialised field data type.
| Constructors | Field | | fieldName :: String | | fieldType :: Q Type | | fieldRead :: Maybe (Q Exp) | | fieldShow :: Maybe (Q Exp) | | fieldDefault :: Maybe (Q Exp) | | fieldConstr :: Maybe String | | fieldIsContainer :: Bool | | fieldIsOptional :: Bool | |
|
|
|
|
|
Generates a simple field.
|
|
|
Sets the renamed constructor field.
|
|
|
Sets the default value on a field (makes it optional with a
default value).
|
|
|
Marks a field optional (turning its base type into a Maybe).
|
|
|
Marks a field as a container.
|
|
|
:: Name | The name of the read function
| -> Name | The name of the show function
| -> Field | The original field
| -> Field | Updated field
| Sets custom functions on a field.
|
|
|
|
|
|
Computes the preferred variable name to use for the value of this
field. If the field has a specific constructor name, then we use a
first-letter-lowercased version of that; otherwise, we simply use
the field name. See also fieldRecordName.
|
|
|
|
|
|
|
:: Field | The field definition
| -> Q Exp | The value of the field as existing in the JSON message
| -> Q Exp | The entire object in JSON object format
| -> Q Exp | Resulting expression
| Produces the expression that will de-serialise a given
field. Since some custom parsing functions might need to use the
entire object, we do take and pass the object to any custom read
functions.
|
|
|
Common field declarations
|
|
|
|
|
|
|
|
Helper functions
|
|
ensureLower :: String -> String | Source |
|
Ensure first letter is lowercase.
Used to convert type name to function prefix, e.g. in data Aa ->
aaToRaw.
|
|
ensureUpper :: String -> String | Source |
|
Ensure first letter is uppercase.
Used to convert constructor name to component
|
|
varNameE :: String -> Q Exp | Source |
|
Helper for quoted expressions.
|
|
|
showJSON as an expression, for reuse.
|
|
toRawName :: String -> Name | Source |
|
ToRaw function name.
|
|
fromRawName :: String -> Name | Source |
|
FromRaw function name.
|
|
reprE :: Either String Name -> Q Exp | Source |
|
Converts a name to it's varE/litE representations.
|
|
appFn :: Exp -> Exp -> Exp | Source |
|
Smarter function application.
This does simply f x, except that if is id, it will skip it, in
order to generate more readable code when using -ddump-splices.
|
|
readContainer :: (Monad m, JSON a) => JSObject JSValue -> m (Container a) | Source |
|
Container loader
|
|
|
Container dumper
|
|
Template code for simple raw type-equivalent ADTs
|
|
strADTDecl :: Name -> [String] -> Dec | Source |
|
Generates a data type declaration.
The type will have a fixed list of instances.
|
|
genToRaw :: Name -> Name -> Name -> [(String, Either String Name)] -> Q [Dec] | Source |
|
Generates a toRaw function.
This generates a simple function of the form:
nameToRaw :: Name -> traw
nameToRaw Cons1 = var1
nameToRaw Cons2 = "value2"
|
|
genFromRaw :: Name -> Name -> Name -> [(String, Name)] -> Q [Dec] | Source |
|
Generates a fromRaw function.
The function generated is monadic and can fail parsing the
raw value. It is of the form:
nameFromRaw :: (Monad m) => traw -> m Name
nameFromRaw s | s == var1 = Cons1
| s == "value2" = Cons2
| otherwise = fail ...
|
|
declareADT :: Name -> String -> [(String, Name)] -> Q [Dec] | Source |
|
Generates a data type from a given raw format.
The format is expected to multiline. The first line contains the
type name, and the rest of the lines must contain two words: the
constructor name and then the string representation of the
respective constructor.
The function will generate the data type declaration, and then two
functions:
- nameToRaw, which converts the type to a raw type
- nameFromRaw, which (monadically) converts from a raw type to the type
Note that this is basically just a custom show/read instance,
nothing else.
|
|
declareIADT :: String -> [(String, Name)] -> Q [Dec] | Source |
|
|
declareSADT :: String -> [(String, Name)] -> Q [Dec] | Source |
|
|
genShowJSON :: String -> Q Dec | Source |
|
Creates the showJSON member of a JSON instance declaration.
This will create what is the equivalent of:
showJSON = showJSON . nameToRaw
in an instance JSON name declaration
|
|
genReadJSON :: String -> Q Dec | Source |
|
Creates the readJSON member of a JSON instance declaration.
This will create what is the equivalent of:
readJSON s = case readJSON s of
Ok s' -> nameFromRaw s'
Error e -> Error description
in an instance JSON name declaration
|
|
makeJSONInstance :: Name -> Q [Dec] | Source |
|
Generates a JSON instance for a given type.
This assumes that the nameToRaw and nameFromRaw functions
have been defined as by the declareSADT function.
|
|
Template code for opcodes
|
|
deCamelCase :: String -> String | Source |
|
Transforms a CamelCase string into an_underscore_based_one.
|
|
camelCase :: String -> String | Source |
|
Transform an underscore_name into a CamelCase one.
|
|
constructorName :: Con -> Q Name | Source |
|
Computes the name of a given constructor.
|
|
genConstrToStr :: (String -> String) -> Name -> String -> Q [Dec] | Source |
|
Builds the generic constructor-to-string function.
This generates a simple function of the following form:
fname (ConStructorOne {}) = trans_fun(ConStructorOne)
fname (ConStructorTwo {}) = trans_fun(ConStructorTwo)
This builds a custom list of name/string pairs and then uses
genToRaw to actually generate the function
|
|
genOpID :: Name -> String -> Q [Dec] | Source |
|
Constructor-to-string for OpCode.
|
|
type OpParam = (String, Q Type, Q Exp) | Source |
|
OpCode parameter (field) type.
|
|
|
:: String | Type name to use
| -> [(String, [Field])] | Constructor name and parameters
| -> Q [Dec] | | Generates the OpCode data type.
This takes an opcode logical definition, and builds both the
datatype and the JSON serialisation out of it. We can't use a
generic serialisation since we need to be compatible with Ganeti's
own, so we have a few quirks to work around.
|
|
|
isOptional :: Type -> Bool | Source |
|
Checks whether a given parameter is options.
This requires that it's a Maybe.
|
|
|
:: String | The constructor name
| -> [Field] | The parameter definitions for this
constructor
| -> Q Clause | Resulting clause
| Generates the "save" clause for an entire opcode constructor.
This matches the opcode with variables named the same as the
constructor fields (just so that the spliced in code looks nicer),
and passes those name plus the parameter definition to saveObjectField.
|
|
|
genSaveOpCode :: [(String, [Field])] -> Q (Dec, Dec) | Source |
|
Generates the main save opcode function.
This builds a per-constructor match clause that contains the
respective constructor-serialisation code.
|
|
|
|
genLoadOpCode :: [(String, [Field])] -> Q (Dec, Dec) | Source |
|
|
Template code for luxi
|
|
genStrOfOp :: Name -> String -> Q [Dec] | Source |
|
Constructor-to-string for LuxiOp.
|
|
genStrOfKey :: Name -> String -> Q [Dec] | Source |
|
Constructor-to-string for MsgKeys.
|
|
type LuxiParam = (String, Q Type, Q Exp) | Source |
|
LuxiOp parameter type.
|
|
|
Generates the LuxiOp data type.
This takes a Luxi operation definition and builds both the
datatype and the function trnasforming the arguments to JSON.
We can't use anything less generic, because the way different
operations are serialized differs on both parameter- and top-level.
There are three things to be defined for each parameter:
- name
- type
- operation; this is the operation performed on the parameter before
serialization
|
|
|
Generates the "save" expression for a single luxi parameter.
|
|
|
Generates the "save" clause for entire LuxiOp constructor.
|
|
|
Generates the main save LuxiOp function.
|
|
Objects functionality
|
|
fieldTypeInfo :: String -> Field -> Q (Name, Strict, Type) | Source |
|
Extract the field's declaration from a Field structure.
|
|
buildObject :: String -> String -> [Field] -> Q [Dec] | Source |
|
Build an object declaration.
|
|
buildObjectSerialisation :: String -> [Field] -> Q [Dec] | Source |
|
|
|
|
|
|
objectShowJSON :: String -> Q Dec | Source |
|
|
genLoadObject :: (Field -> Q (Name, Stmt)) -> String -> [Field] -> Q (Dec, Dec) | Source |
|
|
|
|
objectReadJSON :: String -> Q Dec | Source |
|
|
Inheritable parameter tables implementation
|
|
paramTypeNames :: String -> (String, String) | Source |
|
Compute parameter type names.
|
|
paramFieldTypeInfo :: String -> Field -> Q (Name, Strict, Type) | Source |
|
Compute information about the type of a parameter field.
|
|
buildParam :: String -> String -> [Field] -> Q [Dec] | Source |
|
Build a parameter declaration.
This function builds two different data structures: a filled one,
in which all fields are required, and a partial one, in which all
fields are optional. Due to the current record syntax issues, the
fields need to be named differrently for the two structures, so the
partial ones get a P suffix.
|
|
buildPParamSerialisation :: String -> [Field] -> Q [Dec] | Source |
|
|
|
|
|
|
buildFromMaybe :: String -> Q Dec | Source |
|
Builds a simple declaration of type n_x = fromMaybe f_x p_x.
|
|
fillParam :: String -> String -> [Field] -> Q [Dec] | Source |
|
|
Produced by Haddock version 2.6.0 |