-- | 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
(FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool) -> Eq FieldName
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
Eq FieldName
-> (FieldName -> FieldName -> Ordering)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> Bool)
-> (FieldName -> FieldName -> FieldName)
-> (FieldName -> FieldName -> FieldName)
-> Ord 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
$cp1Ord :: Eq FieldName
Ord)

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

-- | From 'FastString'
--
-- This happens at compile time in the plugin.
fromFastString :: FastString -> FieldName
fromFastString :: FastString -> FieldName
fromFastString = String -> FieldName
forall a. IsString a => String -> a
fromString (String -> FieldName)
-> (FastString -> String) -> FastString -> FieldName
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 (String -> Int
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 = Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s (Int -> Int) -> (FieldName -> Int) -> FieldName -> Int
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 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
11) (ShowS -> ShowS) -> ShowS -> ShowS
forall a b. (a -> b) -> a -> b
$
    String -> ShowS
showString String
"fromString " ShowS -> ShowS -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> ShowS
forall a. Show a => Int -> a -> ShowS
showsPrec Int
11 (FieldName -> String
fieldNameLabel FieldName
n)

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