content: {-# language LambdaCase #-}
  {-# language QuasiQuotes #-}
  {-# language TemplateHaskell #-}
  -- |
  -- Copyright :  (c) 2019 Edward Kmett
  -- License   :  BSD-2-Clause OR Apache-2.0
  -- Maintainer:  Edward Kmett <ekmett@gmail.com>
  -- Stability :  experimental
  -- Portability: non-portable
  --
  module Graphics.FreeType.Private
  ( anti
  , w2c, c2w
  ) where
  
  import Data.Coerce
  import Data.Functor ((<&>))
  import Data.Word
  import qualified Language.C.Inline.Context as C
  import qualified Language.C.Inline.HaskellIdentifier as C
  import qualified Language.C.Types as C
  import qualified Language.Haskell.TH as TH
  
  getHsVariable :: String -> C.HaskellIdentifier -> TH.ExpQ
  getHsVariable err s = TH.lookupValueName (C.unHaskellIdentifier s) >>= \ case
    Nothing -> fail $ "Cannot capture Haskell variable " ++ C.unHaskellIdentifier s ++ ", because it's not in scope. (" ++ err ++ ")"
    Just hsName -> TH.varE hsName
  
  anti :: C.Type C.CIdentifier -> TH.TypeQ -> TH.ExpQ -> C.SomeAntiQuoter
  anti cTy hsTyQ w = C.SomeAntiQuoter C.AntiQuoter
    { C.aqParser = C.parseIdentifier <&> \hId -> (C.mangleHaskellIdentifier False hId, cTy, hId)
    , C.aqMarshaller = \_ _ _ cId -> (,) <$> hsTyQ <*> [|$w (coerce $(getHsVariable "freeTypeCtx" cId))|]
    }
  
  w2c :: Word32 -> Char
  w2c = toEnum . fromIntegral
  
  c2w :: Char -> Word32
  c2w = fromIntegral . fromEnum
  