content: {-# LANGUAGE TemplateHaskell #-}
  
  ------------------------------------------------------------------------------
  -- |
  -- Module:      Database.PostgreSQL.Simple.TypeInfo.Macro
  -- Copyright:   (c) 2013 Leon P Smith
  -- License:     BSD3
  -- Maintainer:  Leon P Smith <leon@melding-monads.com>
  -- Stability:   experimental
  --
  -- A Template Haskell macro for efficiently checking membership in
  -- a set of type oids.
  --
  ------------------------------------------------------------------------------
  
  module Database.PostgreSQL.Simple.TypeInfo.Macro
      ( mkCompats
      , inlineTypoid
      ) where
  
  import Database.PostgreSQL.Simple.TypeInfo.Static
  import Database.PostgreSQL.Simple.Types (Oid(..))
  import Language.Haskell.TH
  
  
  -- | Returns an expression that has type @'Oid' -> 'Bool'@,  true if the
  --   oid is equal to any one of the 'typoid's of the given 'TypeInfo's.
  mkCompats :: [TypeInfo] -> ExpQ
  mkCompats tys = [| \(Oid x) -> $(caseE [| x |] (map alt tys ++ [catchAll])) |]
     where
       alt :: TypeInfo -> MatchQ
       alt ty = match (inlineTypoidP ty) (normalB [| True |]) []
  
       catchAll :: MatchQ
       catchAll = match wildP (normalB [| False |]) []
  
  -- | Literally substitute the 'typoid' of a 'TypeInfo' expression.
  --   Returns an expression of type 'Oid'.  Useful because GHC tends
  --   not to fold constants.
  inlineTypoid :: TypeInfo -> ExpQ
  inlineTypoid ty = [| Oid $(litE (getTypoid ty)) |]
  
  inlineTypoidP :: TypeInfo -> PatQ
  inlineTypoidP ty = litP (getTypoid ty)
  
  getTypoid :: TypeInfo -> Lit
  getTypoid ty = let (Oid x) = typoid ty in integerL (fromIntegral x)
  