    {-|
      Copyright   :  (C) 2012-2016, University of Twente,
                              2017, Google Inc.,
                              2021, QBayLogic B.V.
      License     :  BSD2 (see the file LICENSE)
      Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>

      Data Constructors in CoreHW
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveAnyClass #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE MultiParamTypeClasses #-}

    module Clash.Core.DataCon
      ( DataCon (..)
      , DcName
      , ConTag
      , DcStrictness(..)
      )
    where

    import Control.DeepSeq                        (NFData(..))
    import Data.Binary                            (Binary)
    import Data.Function                          (on)
    import Data.Hashable                          (Hashable)
    import qualified Data.Text                    as Text
    import GHC.Generics                           (Generic)

    import Clash.Core.Name                        (Name (..))
    import {-# SOURCE #-} Clash.Core.Type         (Type)
    import Clash.Core.Var                         (TyVar)
    import Clash.Unique

    -- | Data Constructor
    data DataCon
      = MkData
      { DataCon -> DcName
    dcName :: !DcName
      -- ^ Name of the DataCon
      , DataCon -> Unique
    dcUniq :: {-# UNPACK #-} !Unique
      -- ^ Invariant: forall x . dcUniq x ~ nameUniq (dcName x)
      , DataCon -> Unique
    dcTag :: !ConTag
      -- ^ Syntactical position in the type definition
      , DataCon -> Type
    dcType :: !Type
      -- ^ Type of the 'DataCon
      , DataCon -> [TyVar]
    dcUnivTyVars :: [TyVar]
      -- ^ Universally quantified type-variables, these type variables are also part
      -- of the result type of the DataCon
      , DataCon -> [TyVar]
    dcExtTyVars :: [TyVar]
      -- ^ Existentially quantified type-variables, these type variables are not
      -- part of the result of the DataCon, but only of the arguments.
      , DataCon -> [Type]
    dcArgTys :: [Type]
      -- ^ Argument types
      , DataCon -> [DcStrictness]
    dcArgStrict :: [DcStrictness]
      -- ^ Argument strictness
      , DataCon -> [Text]
    dcFieldLabels :: [Text.Text]
      -- ^ Names of fields. Used when data constructor is referring to a record type.
      } deriving ((forall x. DataCon -> Rep DataCon x)
    -> (forall x. Rep DataCon x -> DataCon) -> Generic DataCon
    forall x. Rep DataCon x -> DataCon
    forall x. DataCon -> Rep DataCon x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. DataCon -> Rep DataCon x
    from :: forall x. DataCon -> Rep DataCon x
    $cto :: forall x. Rep DataCon x -> DataCon
    to :: forall x. Rep DataCon x -> DataCon
    Generic,DataCon -> ()
    (DataCon -> ()) -> NFData DataCon
    forall a. (a -> ()) -> NFData a
    $crnf :: DataCon -> ()
    rnf :: DataCon -> ()
    NFData,Get DataCon
    [DataCon] -> Put
    DataCon -> Put
    (DataCon -> Put)
    -> Get DataCon -> ([DataCon] -> Put) -> Binary DataCon
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: DataCon -> Put
    put :: DataCon -> Put
    $cget :: Get DataCon
    get :: Get DataCon
    $cputList :: [DataCon] -> Put
    putList :: [DataCon] -> Put
    Binary)

    instance Show DataCon where
      show :: DataCon -> String
    show = DcName -> String
    forall a. Show a => a -> String
    show (DcName -> String) -> (DataCon -> DcName) -> DataCon -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . DataCon -> DcName
    dcName

    instance Eq DataCon where
      == :: DataCon -> DataCon -> Bool
    (==) = Unique -> Unique -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) (Unique -> Unique -> Bool)
    -> (DataCon -> Unique) -> DataCon -> DataCon -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` DataCon -> Unique
    dcUniq
      /= :: DataCon -> DataCon -> Bool
    (/=) = Unique -> Unique -> Bool
    forall a. Eq a => a -> a -> Bool
    (/=) (Unique -> Unique -> Bool)
    -> (DataCon -> Unique) -> DataCon -> DataCon -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` DataCon -> Unique
    dcUniq

    instance Ord DataCon where
      compare :: DataCon -> DataCon -> Ordering
    compare = Unique -> Unique -> Ordering
    forall a. Ord a => a -> a -> Ordering
    compare (Unique -> Unique -> Ordering)
    -> (DataCon -> Unique) -> DataCon -> DataCon -> Ordering
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` DataCon -> Unique
    dcUniq

    instance Uniquable DataCon where
      getUnique :: DataCon -> Unique
    getUnique = DataCon -> Unique
    dcUniq
      setUnique :: DataCon -> Unique -> DataCon
    setUnique DataCon
    dc Unique
    u = DataCon
    dc {dcUniq=u, dcName=(dcName dc){nameUniq=u}}

    -- | Syntactical position of the DataCon in the type definition
    type ConTag = Int
    -- | DataCon reference
    type DcName = Name DataCon

    data DcStrictness
      = Strict
      | Lazy
      deriving ((forall x. DcStrictness -> Rep DcStrictness x)
    -> (forall x. Rep DcStrictness x -> DcStrictness)
    -> Generic DcStrictness
    forall x. Rep DcStrictness x -> DcStrictness
    forall x. DcStrictness -> Rep DcStrictness x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cfrom :: forall x. DcStrictness -> Rep DcStrictness x
    from :: forall x. DcStrictness -> Rep DcStrictness x
    $cto :: forall x. Rep DcStrictness x -> DcStrictness
    to :: forall x. Rep DcStrictness x -> DcStrictness
    Generic, DcStrictness -> ()
    (DcStrictness -> ()) -> NFData DcStrictness
    forall a. (a -> ()) -> NFData a
    $crnf :: DcStrictness -> ()
    rnf :: DcStrictness -> ()
    NFData, DcStrictness -> DcStrictness -> Bool
    (DcStrictness -> DcStrictness -> Bool)
    -> (DcStrictness -> DcStrictness -> Bool) -> Eq DcStrictness
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: DcStrictness -> DcStrictness -> Bool
    == :: DcStrictness -> DcStrictness -> Bool
    $c/= :: DcStrictness -> DcStrictness -> Bool
    /= :: DcStrictness -> DcStrictness -> Bool
    Eq, Eq DcStrictness
    Eq DcStrictness =>
    (Unique -> DcStrictness -> Unique)
    -> (DcStrictness -> Unique) -> Hashable DcStrictness
    Unique -> DcStrictness -> Unique
    DcStrictness -> Unique
    forall a.
    Eq a =>
    (Unique -> a -> Unique) -> (a -> Unique) -> Hashable a
    $chashWithSalt :: Unique -> DcStrictness -> Unique
    hashWithSalt :: Unique -> DcStrictness -> Unique
    $chash :: DcStrictness -> Unique
    hash :: DcStrictness -> Unique
    Hashable, Get DcStrictness
    [DcStrictness] -> Put
    DcStrictness -> Put
    (DcStrictness -> Put)
    -> Get DcStrictness
    -> ([DcStrictness] -> Put)
    -> Binary DcStrictness
    forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
    $cput :: DcStrictness -> Put
    put :: DcStrictness -> Put
    $cget :: Get DcStrictness
    get :: Get DcStrictness
    $cputList :: [DcStrictness] -> Put
    putList :: [DcStrictness] -> Put
    Binary)