{-# LANGUAGE TemplateHaskell #-} -- | A tool to generate maps to and from 'Text' values corresponding -- to inhabitants of enumerated types 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 Data.Monoid import Language.Haskell.TH -- | Tool to generate the maps between enumerations and 'Text' strings -- named by 'text_enum_nm' and 'map_enum_nm'. enumTool :: APITool enumTool = apiNodeTool $ apiSpecTool mempty mempty mempty enum mempty where enum = simpleTool (uncurry gen_se_tx) <> simpleTool (gen_se_mp . fst) -- | For an enum type @E@, name a function @_text_E :: E -> 'Text'@ -- that gives a string corresponding to the inhabitant of the type. -- For example, we generate something like this: -- -- > _text_FrameRate :: FrameRate -> T.Text -- > _text_FrameRate fr = -- > case fr of -- > FRauto -> "auto" -- > FR10 -> "10" -- > FR15 -> "15" -- > FR23_97 -> "23.97" -- > FR24 -> "24" -- > FR25 -> "25" -- > FR29_97 -> "29.97" -- > FR30 -> "30" -- > FR60 -> "60" text_enum_nm :: APINode -> Name text_enum_nm an = mkName $ "_text_" ++ (_TypeName $ anName an) gen_se_tx :: APINode -> SpecEnum -> Q [Dec] gen_se_tx as se = simpleSigD (text_enum_nm as) [t| $tc -> T.Text |] bdy where tc = conT $ rep_type_nm as bdy = lamCaseE [ match (pt fnm) (bd fnm) [] | (fnm,_) <- seAlts se ] pt fnm = nodeAltConP as fnm [] bd fnm = normalB $ stringE $ _FieldName fnm -- | For an enum type @E@, name a map from 'Text' values to -- inhabitants of the type, for example: -- -- > _map_FrameRate :: Map Text FrameRate -- > _map_FrameRate = genTextMap _text_FrameRate map_enum_nm :: APINode -> Name map_enum_nm an = mkName $ "_map_" ++ (_TypeName $ anName an) gen_se_mp :: APINode -> Q [Dec] gen_se_mp as = simpleSigD (map_enum_nm as) [t| Map.Map T.Text $tc |] [e| genTextMap $(varE $ text_enum_nm as) |] where tc = conT $ rep_type_nm as genTextMap :: (Ord a,Bounded a,Enum a) => (a->T.Text) -> Map.Map T.Text a genTextMap f = Map.fromList [ (f x,x) | x<-[minBound..maxBound] ]