Safe Haskell | None |
---|
TemplateHaskell helper for Ganeti Haskell code.
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
- data OptionalType
- data Field = Field {
- fieldName :: Text
- fieldType :: Q Type
- fieldRead :: Maybe (Q Exp)
- fieldShow :: Maybe (Q Exp)
- fieldExtraKeys :: [Text]
- fieldDefault :: Maybe (Q Exp)
- fieldSerializeDefault :: Bool
- fieldConstr :: Maybe Text
- fieldIsOptional :: OptionalType
- fieldDoc :: Text
- fieldPresentInForthcoming :: Bool
- simpleField :: String -> Q Type -> Field
- andRestArguments :: String -> Field
- withDoc :: String -> Field -> Field
- renameField :: String -> Field -> Field
- defaultField :: Q Exp -> Field -> Field
- notSerializeDefaultField :: Q Exp -> Field -> Field
- presentInForthcoming :: Field -> Field
- optionalField :: Field -> Field
- optionalNullSerField :: Field -> Field
- makeOptional :: Field -> Field
- customField :: Name -> Name -> [String] -> Field -> Field
- fieldRecordName :: Field -> String
- fieldVariable :: Field -> String
- actualFieldType :: Field -> Q Type
- checkNonOptDef :: MonadFail m => Field -> m ()
- parseFn :: Field -> Q Exp -> Q Exp
- loadFn :: Field -> Q Exp -> Q Exp -> Q Exp
- loadFnOpt :: Field -> Q Exp -> Q Exp -> Q Exp
- type SimpleField = (String, Q Type)
- type SimpleConstructor = (String, [SimpleField])
- type SimpleObject = [SimpleConstructor]
- type OpCodeConstructor = (String, Q Type, String, [Field], String)
- type LuxiConstructor = (String, [Field])
- ensureLower :: String -> String
- ensureUpper :: String -> String
- fromObjE :: Q Exp
- toRawName :: String -> Name
- fromRawName :: String -> Name
- reprE :: Either String Name -> Q Exp
- appCons :: Name -> [Exp] -> Exp
- appConsApp :: Name -> [Exp] -> Exp
- buildConsField :: Q Type -> StrictTypeQ
- buildSimpleCons :: Name -> SimpleObject -> Q Dec
- genSaveSimpleObj :: Name -> String -> SimpleObject -> (SimpleConstructor -> Q Clause) -> Q (Dec, Dec)
- strADTDecl :: Name -> [String] -> Dec
- genToRaw :: Name -> Name -> Name -> [(String, Either String Name)] -> Q [Dec]
- genFromRaw :: Name -> Name -> Name -> [(String, Either String Name)] -> Q [Dec]
- declareADT :: (a -> Either String Name) -> Name -> String -> [(String, a)] -> Q [Dec]
- declareLADT :: Name -> String -> [(String, String)] -> Q [Dec]
- declareILADT :: String -> [(String, Int)] -> 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
- reifyConsNames :: Name -> Q [String]
- genConstrToStr :: (String -> Q String) -> Name -> String -> Q [Dec]
- genOpID :: Name -> String -> Q [Dec]
- genOpLowerStrip :: String -> Name -> String -> Q [Dec]
- genAllConstr :: (String -> String) -> Name -> String -> Q [Dec]
- genAllOpIDs :: Name -> String -> Q [Dec]
- data OpCodeField = OpCodeField {}
- data OpCodeDescriptor = OpCodeDescriptor {}
- maybeApp :: Maybe (Q Exp) -> Q Type -> Q Exp
- genPyType' :: OptionalType -> Q Type -> Q PyType
- genPyType :: Field -> Q PyType
- genPyDefault :: Field -> Q Exp
- pyField :: Field -> Q Exp
- pyClass :: OpCodeConstructor -> Q Exp
- pyClasses :: [OpCodeConstructor] -> Q [Dec]
- opcodeConsToLuxiCons :: OpCodeConstructor -> LuxiConstructor
- genOpCodeDictObject :: Name -> (LuxiConstructor -> Q Clause) -> (LuxiConstructor -> Q Exp) -> [LuxiConstructor] -> Q [Dec]
- genOpCode :: String -> [OpCodeConstructor] -> Q [Dec]
- genOpConsFields :: OpCodeConstructor -> Clause
- genAllOpFields :: String -> [OpCodeConstructor] -> (Dec, Dec)
- saveConstructor :: LuxiConstructor -> Q Clause
- genSaveOpCode :: [LuxiConstructor] -> (LuxiConstructor -> Q Clause) -> Q [Clause]
- loadConstructor :: Name -> (Field -> Q Exp) -> [Field] -> Q Exp
- loadOpConstructor :: LuxiConstructor -> Q Exp
- genLoadOpCode :: [LuxiConstructor] -> (LuxiConstructor -> Q Exp) -> Q [Clause]
- genStrOfOp :: Name -> String -> Q [Dec]
- genStrOfKey :: Name -> String -> Q [Dec]
- genLuxiOp :: String -> [LuxiConstructor] -> Q [Dec]
- saveLuxiConstructor :: LuxiConstructor -> Q Clause
- fieldTypeInfo :: String -> Field -> Q (Name, Strict, Type)
- buildObject :: String -> String -> [Field] -> Q [Dec]
- buildAccessor :: Name -> String -> Name -> String -> Name -> String -> Field -> Q [Dec]
- buildLens :: (Name, Name) -> (Name, Name) -> Name -> String -> Int -> (Field, Int) -> Q [Dec]
- buildObjectWithForthcoming :: String -> String -> [Field] -> Q [Dec]
- buildObjectSerialisation :: String -> [Field] -> Q [Dec]
- objVarName :: Name
- defaultToJSArray :: DictObject a => [String] -> a -> [JSValue]
- defaultFromJSArray :: DictObject a => [String] -> [JSValue] -> Result a
- genArrayObjectInstance :: Name -> [Field] -> Q Dec
- genDictObject :: (Name -> Field -> Q Exp) -> (Field -> Q Exp) -> String -> [Field] -> Q [Dec]
- genSaveObject :: String -> Q [Dec]
- saveObjectField :: Name -> Field -> Q Exp
- objectShowJSON :: String -> Q Dec
- genLoadObject :: String -> Q (Dec, Dec)
- loadObjectField :: [Field] -> Field -> Q Exp
- fieldsKeys :: [Field] -> [String]
- fieldsDictKeys :: [Field] -> Exp
- fieldsDictKeysQ :: [Field] -> Q Exp
- fieldsUsedKeysQ :: [Field] -> Q Exp
- objectReadJSON :: String -> Q Dec
- paramTypeNames :: String -> (String, String)
- paramFieldNames :: String -> Field -> (Name, Name)
- paramFieldTypeInfo :: String -> Field -> VarStrictTypeQ
- buildParam :: String -> String -> [Field] -> Q [Dec]
- buildParamAllFields :: String -> [Field] -> [Dec]
- buildPParamSerialisation :: String -> [Field] -> Q [Dec]
- savePParamField :: Name -> Field -> Q Exp
- loadPParamField :: Field -> Q Exp
- fillParam :: String -> String -> [Field] -> Q [Dec]
- excErrMsg :: (String, Q Type)
- genException :: String -> SimpleObject -> Q [Dec]
- saveExcCons :: String -> [SimpleField] -> Q Clause
- loadExcConstructor :: Name -> String -> [SimpleField] -> Q Exp
- genLoadExc :: Name -> String -> SimpleObject -> Q (Dec, Dec)
- ssconfConstructorName :: String -> String
Exported types
data OptionalType Source #
Optional field information.
NotOptional | Field is not optional |
OptionalOmitNull | Field is optional, null is not serialised |
OptionalSerializeNull | Field is optional, null is serialised |
AndRestArguments | Special field capturing all the remaining fields as plain JSON values |
Serialised field data type describing how to generate code for the field.
Each field has a type, which isn't captured in the type of the data type,
but is saved in the Q
monad in fieldType
.
Let t
be a type we want to parametrize the field with. There are the
following possible types of fields:
- Mandatory with no default.
- Then
fieldType
holdst
,fieldDefault = Nothing
andfieldIsOptional = NotOptional
. - Field with a default value.
- Then
fieldType
holdst
andfieldDefault = Just exp
whereexp
is an expression of typet
andfieldIsOptional = NotOptional
. - Optional, no default value.
- Then
fieldType
holdsMaybe t
,fieldDefault = Nothing
andfieldIsOptional
is eitherOptionalOmitNull
orOptionalSerializeNull
.
Optional fields with a default value are prohibited, as their main intention is to represent the information that a request didn't contain the field data.
Custom (de)serialization:
Field can have custom (de)serialization functions that are stored in
fieldRead
and fieldShow
. If they aren't provided, the default is to use
readJSON
and showJSON
for the field's type t
. If they are provided,
the type of the contained deserializing expression must be
[(String, JSON.JSValue)] -> JSON.JSValue -> JSON.Result t
where the first argument carries the whole record in the case the deserializing function needs to process additional information.
The type of the contained serializing experssion must be
t -> (JSON.JSValue, [(String, JSON.JSValue)])
where the result can provide extra JSON fields to include in the output
record (or just return []
if they're not needed).
Note that for optional fields the type appearing in the custom functions
is still t
. Therefore making a field optional doesn't change the
functions.
There is also a special type of optional field AndRestArguments
which
allows to parse any additional arguments not covered by other fields. There
can be at most one such special field and it's type must be
Map String JSON.JSValue
. See also andRestArguments
.
Field | |
|
simpleField :: String -> Q Type -> Field Source #
Generates a simple field.
andRestArguments :: String -> Field Source #
Generate an AndRestArguments catch-all field.
renameField :: String -> Field -> Field Source #
Sets the renamed constructor field.
defaultField :: Q Exp -> Field -> Field Source #
Sets the default value on a field (makes it optional with a default value).
notSerializeDefaultField :: Q Exp -> Field -> Field Source #
A defaultField which will be serialized only if it's value differs from a default value.
presentInForthcoming :: Field -> Field Source #
Mark a field as present in the forthcoming variant.
optionalField :: Field -> Field Source #
Marks a field optional (turning its base type into a Maybe).
optionalNullSerField :: Field -> Field Source #
Marks a field optional (turning its base type into a Maybe), but
with Nothing
serialised explicitly as null.
makeOptional :: Field -> Field Source #
Make a field optional, if it isn't already.
:: Name | The name of the read function |
-> Name | The name of the show function |
-> [String] | The name of extra field keys |
-> Field | The original field |
-> Field | Updated field |
Sets custom functions on a field.
fieldRecordName :: Field -> String Source #
Computes the record name for a given field, based on either the string value in the JSON serialisation or the custom named if any exists.
fieldVariable :: Field -> String Source #
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
.
actualFieldType :: Field -> Q Type Source #
Compute the actual field type (taking into account possible optional status).
checkNonOptDef :: MonadFail m => Field -> m () Source #
Checks that a given field is not optional (for object types or fields which should not allow this case).
:: Field | The field definition |
-> Q Exp | The entire object in JSON object format |
-> Q Exp | The resulting function that parses a JSON message |
Construct a function that parses a field value. If the field has
a custom fieldRead
, it's applied to o
and used. Otherwise
JSON.readJSON
is used.
:: 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.
:: Field | The field definition |
-> Q Exp | The value of the field as existing in the JSON message as Maybe |
-> Q Exp | The entire object in JSON object format |
-> Q Exp | Resulting expression |
Just as loadFn
, but for optional fields.
Internal types
type SimpleField = (String, Q Type) Source #
A simple field, in constrast to the customisable Field
type.
type SimpleConstructor = (String, [SimpleField]) Source #
A definition for a single constructor for a simple object.
type SimpleObject = [SimpleConstructor] Source #
A definition for ADTs with simple fields.
type OpCodeConstructor = (String, Q Type, String, [Field], String) Source #
A type alias for an opcode constructor of a regular object.
type LuxiConstructor = (String, [Field]) Source #
A type alias for a Luxi constructor of a regular object.
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
fromRawName :: String -> Name Source #
FromRaw function name.
appConsApp :: Name -> [Exp] -> Exp Source #
Apply a constructor to a list of applicative expressions
buildConsField :: Q Type -> StrictTypeQ Source #
Builds a field for a normal constructor.
buildSimpleCons :: Name -> SimpleObject -> Q Dec Source #
Builds a constructor based on a simple definition (not field-based).
:: Name | Object type |
-> String | Function name |
-> SimpleObject | Object definition |
-> (SimpleConstructor -> Q Clause) | Constructor save fn |
-> Q (Dec, Dec) |
Generate the save function for a given type.
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, Either 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 :: (a -> Either String Name) -> Name -> String -> [(String, a)] -> 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.
declareLADT :: Name -> String -> [(String, String)] -> Q [Dec] Source #
declareILADT :: String -> [(String, Int)] -> Q [Dec] Source #
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.
constructorName :: Con -> Q Name Source #
Computes the name of a given constructor.
reifyConsNames :: Name -> Q [String] Source #
Extract all constructor names from a given type.
genConstrToStr :: (String -> Q 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.
genOpLowerStrip :: String -> Name -> String -> Q [Dec] Source #
Strips Op
from the constructor name, converts to lower-case
and adds a given prefix.
genAllConstr :: (String -> String) -> Name -> String -> Q [Dec] Source #
Builds a list with all defined constructor names for a type.
vstr :: String vstr = [...]
Where the actual values of the string are the constructor names
mapped via trans_fun
.
genAllOpIDs :: Name -> String -> Q [Dec] Source #
Generates a list of all defined opcode IDs.
Python code generation
data OpCodeField Source #
data OpCodeDescriptor Source #
Transfers opcode data between the opcode description (through
genOpCode
) and the Python code generation functions.
maybeApp :: Maybe (Q Exp) -> Q Type -> Q Exp Source #
Optionally encapsulates default values in PyValueEx
.
maybeApp exp typ
returns a quoted expression that encapsulates
the default value exp
of an opcode parameter cast to typ
in a
PyValueEx
, if exp
is Just
. Otherwise, it returns a quoted
expression with Nothing
.
genPyType' :: OptionalType -> Q Type -> Q PyType Source #
Generates a Python type according to whether the field is optional.
The type of created expression is PyType.
genPyDefault :: Field -> Q Exp Source #
Generates Python default values from opcode parameters.
pyClass :: OpCodeConstructor -> Q Exp Source #
Generates a Haskell function call to "showPyClass" with the necessary information on how to build the Python class string.
pyClasses :: [OpCodeConstructor] -> Q [Dec] Source #
Generates a function called "pyClasses" that holds the list of all the opcode descriptors necessary for generating the Python opcodes.
opcodeConsToLuxiCons :: OpCodeConstructor -> LuxiConstructor Source #
Converts from an opcode constructor to a Luxi constructor.
:: Name | Type name to use |
-> (LuxiConstructor -> Q Clause) | saving function |
-> (LuxiConstructor -> Q Exp) | loading function |
-> [LuxiConstructor] | Constructors |
-> Q [Dec] |
Generates DictObject
instance for an op-code.
:: String | Type name to use |
-> [OpCodeConstructor] | 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.
genOpConsFields :: OpCodeConstructor -> Clause Source #
Generates the function pattern returning the list of fields for a given constructor.
:: String | Function name |
-> [OpCodeConstructor] | Object definition |
-> (Dec, Dec) |
Generates a list of all fields of an opcode constructor.
:: LuxiConstructor | The 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
.
:: [LuxiConstructor] | Object definition |
-> (LuxiConstructor -> Q Clause) | Constructor save fn |
-> Q [Clause] |
Generates the main save opcode function, serializing as a dictionary.
This builds a per-constructor match clause that contains the respective constructor-serialisation code.
loadConstructor :: Name -> (Field -> Q Exp) -> [Field] -> Q Exp Source #
Generates load code for a single constructor of the opcode data type.
The type of the resulting expression is WriterT UsedKeys J.Result a
.
loadOpConstructor :: LuxiConstructor -> Q Exp Source #
Generates load code for a single constructor of the opcode data type.
:: [LuxiConstructor] | |
-> (LuxiConstructor -> Q Exp) | Constructor load fn |
-> Q [Clause] |
Generates the loadOpCode function.
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.
genLuxiOp :: String -> [LuxiConstructor] -> Q [Dec] Source #
Generates the LuxiOp data type.
This takes a Luxi operation definition and builds both the datatype and the function transforming 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 two things to be defined for each parameter:
- name
- type
saveLuxiConstructor :: LuxiConstructor -> Q Clause Source #
Generates the "save" clause for entire LuxiOp constructor.
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.
:: Name | name of the forthcoming constructor |
-> String | prefix for the forthcoming field |
-> Name | name of the real constructor |
-> String | prefix for the real field |
-> Name | name of the generated accessor |
-> String | prefix of the generated accessor |
-> Field | field description |
-> Q [Dec] |
Build an accessor function for a field of an object that can have a forthcoming variant.
:: (Name, Name) | names of the forthcoming constructors |
-> (Name, Name) | names of the real constructors |
-> Name | name of the type |
-> String | the field prefix |
-> Int | arity |
-> (Field, Int) | the Field to generate the lens for, and its position |
-> Q [Dec] |
Build lense declartions for a field.
If the type of the field is the same in the forthcoming and the real variant, the lens will be a simple lens (Lens' s a).
Otherwise, the type will be (Lens s s (Maybe a) a). This is because the field in forthcoming variant has type (Maybe a), but the real variant has type a.
buildObjectWithForthcoming Source #
:: String | Name of the newly defined type |
-> String | base prefix for field names; for the real and forthcoming variant, with base prefix will be prefixed with "real" and forthcoming, respectively. |
-> [Field] | List of fields in the real version |
-> Q [Dec] |
Build an object that can have a forthcoming variant. This will create 3 data types: two objects, prefixed by Real and Forthcoming, respectively, and a sum type of those. The JSON representation of the latter will be a JSON object, dispatching on the "forthcoming" key.
buildObjectSerialisation :: String -> [Field] -> Q [Dec] Source #
Generates an object definition: data type and its JSON instance.
objVarName :: Name Source #
An internal name used for naming variables that hold the entire
object of type [(String,JSValue)]
.
defaultToJSArray :: DictObject a => [String] -> a -> [JSValue] Source #
Provides a default toJSArray
for ArrayObject
instance using its
existing DictObject
instance. The keys are serialized in the order
they're declared. The list must contain all keys possibly generated by
toDict
.
defaultFromJSArray :: DictObject a => [String] -> [JSValue] -> Result a Source #
Provides a default fromJSArray
for ArrayObject
instance using its
existing DictObject
instance. The fields are deserialized in the order
they're declared.
genArrayObjectInstance :: Name -> [Field] -> Q Dec Source #
Generates an additional ArrayObject
instance using its
existing DictObject
instance.
See defaultToJSArray
and defaultFromJSArray
.
:: (Name -> Field -> Q Exp) | a saving function |
-> (Field -> Q Exp) | a loading function |
-> String | an object name |
-> [Field] | a list of fields |
-> Q [Dec] |
Generates DictObject
instance.
genSaveObject :: String -> Q [Dec] Source #
Generates the save object functionality.
saveObjectField :: Name -> Field -> Q Exp Source #
Generates the code for saving an object's field, handling the various types of fields that we have.
objectShowJSON :: String -> Q Dec Source #
Generates the showJSON clause for a given object name.
genLoadObject :: String -> Q (Dec, Dec) Source #
Generates the load object functionality.
loadObjectField :: [Field] -> Field -> Q Exp Source #
Generates code for loading an object's field.
fieldsKeys :: [Field] -> [String] Source #
fieldsDictKeys :: [Field] -> Exp Source #
Generates the set of all used JSON dictionary keys for a list of fields The equivalent of S.fromList (map T.pack ["f1", "f2", "f3"] )
fieldsDictKeysQ :: [Field] -> Q Exp Source #
Generates the list of all used JSON dictionary keys for a list of fields
fieldsUsedKeysQ :: [Field] -> Q Exp Source #
Generates the list of all used JSON dictionary keys for a list of fields,
depending on if any of them has AndRestArguments
flag.
objectReadJSON :: String -> Q Dec Source #
Builds the readJSON instance for a given object name.
Inheritable parameter tables implementation
paramTypeNames :: String -> (String, String) Source #
Compute parameter type names.
paramFieldNames :: String -> Field -> (Name, Name) Source #
Compute the name of a full and a partial parameter field.
paramFieldTypeInfo :: String -> Field -> VarStrictTypeQ 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. Also generate a default value for the partial parameters.
buildParamAllFields :: String -> [Field] -> [Dec] Source #
Builds a list of all fields of a parameter.
buildPParamSerialisation :: String -> [Field] -> Q [Dec] Source #
Generates the serialisation for a partial parameter.
savePParamField :: Name -> Field -> Q Exp Source #
Generates code to save an optional parameter field.
loadPParamField :: Field -> Q Exp Source #
Generates code to load an optional parameter field.
fillParam :: String -> String -> [Field] -> Q [Dec] Source #
Builds a function that executes the filling of partial parameter from a full copy (similar to Python's fillDict).
Template code for exceptions
:: String | Name of new type |
-> SimpleObject | Constructor name and parameters |
-> Q [Dec] |
Builds an exception type definition.
:: String | The constructor name |
-> [SimpleField] | The parameter definitions for this constructor |
-> Q Clause | Resulting clause |
Generates the "save" clause for an entire exception constructor.
This matches the exception with variables named the same as the constructor fields (just so that the spliced in code looks nicer), and calls showJSON on it.
loadExcConstructor :: Name -> String -> [SimpleField] -> Q Exp Source #
Generates load code for a single constructor of an exception.
Generates the code (if there's only one argument, we will use a list, not a tuple:
do (x1, x2, ...) <- readJSON args return $ Cons x1 x2 ...
genLoadExc :: Name -> String -> SimpleObject -> Q (Dec, Dec) Source #
Generates the loadException function.
This generates a quite complicated function, along the lines of:
loadFn (JSArray [JSString name, args]) = case name of A1 -> do (x1, x2, ...) <- readJSON args return $ A1 x1 x2 ... "a2" -> ... s -> fail $ "Unknown exception" ++ s loadFn v = fail $ "Expected array but got " ++ show v
ssconfConstructorName :: String -> String Source #
Compute the ssconf constructor name from its file name.