-- | Field name
--
-- Intended for qualified import.
--
-- > import Data.Record.Anon.Internal.Core.FieldName (FieldName(..))
-- > import qualified Data.Record.Anon.Internal.Core.FieldName as FieldName
module Data.Record.Anon.Internal.Core.FieldName (
    -- * Definition
    FieldName(..)
    -- * Conversion
  , fromString
  , fromFastString
  ) where

import Data.Hashable
import Data.String

import Data.Record.Anon.Internal.Plugin.TC.GhcTcPluginAPI

{-------------------------------------------------------------------------------
  Definition
-------------------------------------------------------------------------------}

-- | Record field name
--
-- A fieldname carries its own hash, which is computed by the plugin at
-- compile time.
data FieldName = FieldName {
      FieldName -> Int
fieldNameHash  :: Int
    , FieldName -> String
fieldNameLabel :: String
    }
  -- For the 'Eq' and 'Ord' instances it's important the 'Int' comes first
  deriving (FieldName -> FieldName -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FieldName -> FieldName -> Bool
$c/= :: FieldName -> FieldName -> Bool
== :: FieldName -> FieldName -> Bool
$c== :: FieldName -> FieldName -> Bool
Eq, Eq FieldName
FieldName -> FieldName -> Bool
FieldName -> FieldName -> Ordering
FieldName -> FieldName -> FieldName
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: FieldName -> FieldName -> FieldName
$cmin :: FieldName -> FieldName -> FieldName
max :: FieldName -> FieldName -> FieldName
$cmax :: FieldName -> FieldName -> FieldName
>= :: FieldName -> FieldName -> Bool
$c>= :: FieldName -> FieldName -> Bool
> :: FieldName -> FieldName -> Bool
$c> :: FieldName -> FieldName -> Bool
<= :: FieldName -> FieldName -> Bool
$c<= :: FieldName -> FieldName -> Bool
< :: FieldName -> FieldName -> Bool
$c< :: FieldName -> FieldName -> Bool
compare :: FieldName -> FieldName -> Ordering
$ccompare :: FieldName -> FieldName -> Ordering
Ord)

{-------------------------------------------------------------------------------
  Conversion
-------------------------------------------------------------------------------}

-- | From 'FastString'
--
-- This happens at compile time in the plugin.
fromFastString :: FastString -> FieldName
fromFastString :: FastString -> FieldName
fromFastString = forall a. IsString a => String -> a
fromString forall b c a. (b -> c) -> (a -> b) -> a -> c
. FastString -> String
unpackFS

{-------------------------------------------------------------------------------
  Instances
-------------------------------------------------------------------------------}

-- | Convenience constructor for 'FieldName'
--
-- This function is primarily for use in the 'Show' instance and for debugging.
-- Other applications should use 'fieldNameVal' instead, so that the hash
-- is computed at compile time instead.
instance IsString FieldName where
  fromString :: String -> FieldName
fromString String
str = Int -> String -> FieldName
FieldName (forall a. Hashable a => a -> Int
hash String
str) String
str

instance Hashable FieldName where
  hash :: FieldName -> Int
hash           = FieldName -> Int
fieldNameHash
  hashWithSalt :: Int -> FieldName -> Int
hashWithSalt Int
s = forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> Int
fieldNameHash

instance Show FieldName where
  showsPrec :: Int -> FieldName -> ShowS
showsPrec Int
p FieldName
n = Bool -> ShowS -> ShowS
showParen (Int
p forall a. Ord a => a -> a -> Bool
>= Int
11) forall a b. (a -> b) -> a -> b
$
    String -> ShowS
showString String
"fromString " forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 (FieldName -> String
fieldNameLabel FieldName
n)

instance Outputable FieldName where
  ppr :: FieldName -> SDoc
ppr = forall a. Outputable a => a -> SDoc
ppr forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> String
fieldNameLabel