{-# LANGUAGE TemplateHaskell #-}
module Data.API.Tools.Enum
( enumTool
, text_enum_nm
, map_enum_nm
) where
import Data.API.TH
import Data.API.Tools.Combinators
import Data.API.Tools.Datatypes
import Data.API.Types
import qualified Data.Text as T
import qualified Data.Map as Map
import Language.Haskell.TH
enumTool :: APITool
enumTool :: APITool
enumTool = Tool APINode -> APITool
apiNodeTool (Tool APINode -> APITool) -> Tool APINode -> APITool
forall a b. (a -> b) -> a -> b
$ Tool (APINode, SpecNewtype)
-> Tool (APINode, SpecRecord)
-> Tool (APINode, SpecUnion)
-> Tool (APINode, SpecEnum)
-> Tool (APINode, APIType)
-> Tool APINode
apiSpecTool Tool (APINode, SpecNewtype)
forall a. Monoid a => a
mempty Tool (APINode, SpecRecord)
forall a. Monoid a => a
mempty Tool (APINode, SpecUnion)
forall a. Monoid a => a
mempty Tool (APINode, SpecEnum)
enum Tool (APINode, APIType)
forall a. Monoid a => a
mempty
where
enum :: Tool (APINode, SpecEnum)
enum = ((APINode, SpecEnum) -> Q [Dec]) -> Tool (APINode, SpecEnum)
forall a. (a -> Q [Dec]) -> Tool a
simpleTool ((APINode -> SpecEnum -> Q [Dec]) -> (APINode, SpecEnum) -> Q [Dec]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry APINode -> SpecEnum -> Q [Dec]
gen_se_tx) Tool (APINode, SpecEnum)
-> Tool (APINode, SpecEnum) -> Tool (APINode, SpecEnum)
forall a. Semigroup a => a -> a -> a
<> ((APINode, SpecEnum) -> Q [Dec]) -> Tool (APINode, SpecEnum)
forall a. (a -> Q [Dec]) -> Tool a
simpleTool (APINode -> Q [Dec]
gen_se_mp (APINode -> Q [Dec])
-> ((APINode, SpecEnum) -> APINode)
-> (APINode, SpecEnum)
-> Q [Dec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (APINode, SpecEnum) -> APINode
forall a b. (a, b) -> a
fst)
text_enum_nm :: APINode -> Name
text_enum_nm :: APINode -> Name
text_enum_nm APINode
an = String -> Name
mkName (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ String
"_text_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (TypeName -> Text
_TypeName (TypeName -> Text) -> TypeName -> Text
forall a b. (a -> b) -> a -> b
$ APINode -> TypeName
anName APINode
an)
gen_se_tx :: APINode -> SpecEnum -> Q [Dec]
gen_se_tx :: APINode -> SpecEnum -> Q [Dec]
gen_se_tx APINode
as SpecEnum
se = Name -> TypeQ -> ExpQ -> Q [Dec]
simpleSigD (APINode -> Name
text_enum_nm APINode
as)
[t| $tc -> T.Text |]
ExpQ
bdy
where
tc :: TypeQ
tc = Name -> TypeQ
conT (Name -> TypeQ) -> Name -> TypeQ
forall a b. (a -> b) -> a -> b
$ APINode -> Name
rep_type_nm APINode
as
bdy :: ExpQ
bdy = [MatchQ] -> ExpQ
lamCaseE [ PatQ -> BodyQ -> [DecQ] -> MatchQ
match (FieldName -> PatQ
pt FieldName
fnm) (FieldName -> BodyQ
bd FieldName
fnm) []
| (FieldName
fnm,String
_) <- SpecEnum -> [(FieldName, String)]
seAlts SpecEnum
se ]
pt :: FieldName -> PatQ
pt FieldName
fnm = APINode -> FieldName -> [PatQ] -> PatQ
nodeAltConP APINode
as FieldName
fnm []
bd :: FieldName -> BodyQ
bd FieldName
fnm = ExpQ -> BodyQ
normalB (ExpQ -> BodyQ) -> ExpQ -> BodyQ
forall a b. (a -> b) -> a -> b
$ String -> ExpQ
stringE (String -> ExpQ) -> String -> ExpQ
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ FieldName -> Text
_FieldName FieldName
fnm
map_enum_nm :: APINode -> Name
map_enum_nm :: APINode -> Name
map_enum_nm APINode
an = String -> Name
mkName (String -> Name) -> String -> Name
forall a b. (a -> b) -> a -> b
$ String
"_map_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack (TypeName -> Text
_TypeName (TypeName -> Text) -> TypeName -> Text
forall a b. (a -> b) -> a -> b
$ APINode -> TypeName
anName APINode
an)
gen_se_mp :: APINode -> Q [Dec]
gen_se_mp :: APINode -> Q [Dec]
gen_se_mp APINode
as = Name -> TypeQ -> ExpQ -> Q [Dec]
simpleSigD (APINode -> Name
map_enum_nm APINode
as)
[t| Map.Map T.Text $tc |]
[e| genTextMap $(varE $ text_enum_nm as) |]
where
tc :: TypeQ
tc = Name -> TypeQ
conT (Name -> TypeQ) -> Name -> TypeQ
forall a b. (a -> b) -> a -> b
$ APINode -> Name
rep_type_nm APINode
as
genTextMap :: (Ord a,Bounded a,Enum a) => (a->T.Text) -> Map.Map T.Text a
genTextMap :: (a -> Text) -> Map Text a
genTextMap a -> Text
f = [(Text, a)] -> Map Text a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [ (a -> Text
f a
x,a
x) | a
x<-[a
forall a. Bounded a => a
minBound..a
forall a. Bounded a => a
maxBound] ]