packages feed

domain-0.1: library/Domain/TH/InstanceDec.hs

{-|
Model-adapted instance declaration templates.
-}
module Domain.TH.InstanceDec
where

import Domain.Prelude
import DomainCore.Model
import qualified Language.Haskell.TH as TH
import qualified DomainCore.TH as CoreTH
import qualified Data.Text as Text
import qualified THLego.Instances as Instances
import qualified THLego.Helpers as Helpers


-- * HasField
-------------------------

enumHasField :: Text -> Text -> TH.Dec
enumHasField typeName label =
  Instances.enumHasField fieldLabel ownerType constructorName
  where
    fieldLabel =
      Helpers.textTyLit label
    ownerType =
      TH.ConT (Helpers.textName typeName)
    constructorName =
      CoreTH.sumConstructorName typeName label

sumHasField :: Text -> Text -> [Type] -> TH.Dec
sumHasField typeName label memberTypes =
  if null memberTypes
    then 
      Instances.enumHasField thFieldLabel thOwnerType thConstructorName
    else
      Instances.sumHasField thFieldLabel thOwnerType thConstructorName thMemberTypes
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label
    thMemberTypes =
      fmap CoreTH.typeType memberTypes

productHasField :: Text -> Text -> Type -> Int -> Int -> TH.Dec
productHasField typeName fieldName projectionType numMemberTypes offset =
  Instances.productHasField thFieldLabel thOwnerType thProjectionType
    thConstructorName numMemberTypes offset
  where
    thFieldLabel =
      Helpers.textTyLit fieldName
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thProjectionType =
      CoreTH.typeType projectionType
    thConstructorName =
      Helpers.textName typeName


-- * IsLabel
-------------------------

-- ** Accessor
-------------------------

productAccessorIsLabel :: Text -> Text -> Type -> Int -> Int -> TH.Dec
productAccessorIsLabel typeName fieldName projectionType numMemberTypes offset =
  Instances.productAccessorIsLabel
    thFieldLabel thOwnerType thProjectionType thConstructorName
    numMemberTypes offset
  where
    thFieldLabel =
      Helpers.textTyLit fieldName
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thProjectionType =
      CoreTH.typeType projectionType
    thConstructorName =
      Helpers.textName typeName

sumAccessorIsLabel :: Text -> Text -> [Type] -> TH.Dec
sumAccessorIsLabel typeName label memberTypes =
  if null memberTypes
    then
      Instances.enumAccessorIsLabel
        thFieldLabel thOwnerType thConstructorName
    else
      Instances.sumAccessorIsLabel
        thFieldLabel thOwnerType thConstructorName thMemberTypes
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label
    thMemberTypes =
      fmap CoreTH.typeType memberTypes

enumAccessorIsLabel :: Text -> Text -> TH.Dec
enumAccessorIsLabel typeName label =
  Instances.enumAccessorIsLabel
    thFieldLabel thOwnerType thConstructorName
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label

-- ** Constructor
-------------------------

curriedSumConstructorIsLabel :: Text -> Text -> [Type] -> TH.Dec
curriedSumConstructorIsLabel typeName label memberTypes =
  Instances.sumConstructorIsLabel
    thFieldLabel thOwnerType thConstructorName thMemberTypes
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label
    thMemberTypes =
      fmap CoreTH.typeType memberTypes

uncurriedSumConstructorIsLabel :: Text -> Text -> [Type] -> TH.Dec
uncurriedSumConstructorIsLabel typeName label memberTypes =
  Instances.tupleAdtConstructorIsLabel
    thFieldLabel thOwnerType thConstructorName thMemberTypes
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label
    thMemberTypes =
      fmap CoreTH.typeType memberTypes

enumConstructorIsLabel :: Text -> Text -> TH.Dec
enumConstructorIsLabel typeName label =
  Instances.enumConstructorIsLabel
    thFieldLabel thOwnerType thConstructorName
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label

wrapperConstructorIsLabel :: Text -> Type -> TH.Dec
wrapperConstructorIsLabel typeName memberType =
  Instances.newtypeConstructorIsLabel
    thFieldLabel thOwnerType thConstructorName thMemberType
  where
    thFieldLabel =
      TH.StrTyLit "value"
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      Helpers.textName typeName
    thMemberType =
      CoreTH.typeType memberType

-- ** Mapper
-------------------------

wrapperMapperIsLabel :: Text -> Type -> TH.Dec
wrapperMapperIsLabel typeName memberType =
  Instances.productMapperIsLabel
    thFieldLabel thOwnerType thMemberType thConstructorName 1 0
  where
    thFieldLabel =
      TH.StrTyLit "value"
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      Helpers.textName typeName
    thMemberType =
      CoreTH.typeType memberType

productMapperIsLabel :: Text -> Text -> Type -> Int -> Int -> TH.Dec
productMapperIsLabel typeName fieldName projectionType numMemberTypes offset =
  Instances.productMapperIsLabel
    thFieldLabel thOwnerType thProjectionType thConstructorName
    numMemberTypes offset
  where
    thFieldLabel =
      Helpers.textTyLit fieldName
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thProjectionType =
      CoreTH.typeType projectionType
    thConstructorName =
      Helpers.textName typeName

sumMapperIsLabel :: Text -> Text -> [Type] -> TH.Dec
sumMapperIsLabel typeName label memberTypes =
  Instances.sumMapperIsLabel
    thFieldLabel thOwnerType thConstructorName thMemberTypes
  where
    thFieldLabel =
      Helpers.textTyLit label
    thOwnerType =
      TH.ConT (Helpers.textName typeName)
    thConstructorName =
      CoreTH.sumConstructorName typeName label
    thMemberTypes =
      fmap CoreTH.typeType memberTypes


-- *
-------------------------

deriving_ :: TH.Name -> Text -> TH.Dec
deriving_ className typeNameText =
  TH.StandaloneDerivD Nothing [] headType
  where
    headType =
      TH.AppT (TH.ConT className) (TH.ConT (Helpers.textName typeNameText))

empty :: TH.Name -> Text -> TH.Dec
empty className typeNameText =
  TH.InstanceD Nothing [] headType []
  where
    headType =
      TH.AppT (TH.ConT className) (TH.ConT (Helpers.textName typeNameText))