{-|
  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
$cto :: forall x. Rep DataCon x -> DataCon
$cfrom :: forall x. DataCon -> Rep DataCon x
Generic,DataCon -> ()
(DataCon -> ()) -> NFData DataCon
forall a. (a -> ()) -> NFData a
rnf :: DataCon -> ()
$crnf :: 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
putList :: [DataCon] -> Put
$cputList :: [DataCon] -> Put
get :: Get DataCon
$cget :: Get DataCon
put :: DataCon -> Put
$cput :: 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 :: Unique
dcUniq=Unique
u, dcName :: DcName
dcName=(DataCon -> DcName
dcName DataCon
dc){nameUniq :: Unique
nameUniq=Unique
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
$cto :: forall x. Rep DcStrictness x -> DcStrictness
$cfrom :: forall x. DcStrictness -> Rep DcStrictness x
Generic, DcStrictness -> ()
(DcStrictness -> ()) -> NFData DcStrictness
forall a. (a -> ()) -> NFData a
rnf :: DcStrictness -> ()
$crnf :: DcStrictness -> ()
NFData, DcStrictness -> DcStrictness -> Bool
(DcStrictness -> DcStrictness -> Bool)
-> (DcStrictness -> DcStrictness -> Bool) -> Eq DcStrictness
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DcStrictness -> DcStrictness -> Bool
$c/= :: DcStrictness -> DcStrictness -> Bool
== :: DcStrictness -> DcStrictness -> Bool
$c== :: 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
hash :: DcStrictness -> Unique
$chash :: DcStrictness -> Unique
hashWithSalt :: Unique -> DcStrictness -> Unique
$chashWithSalt :: Unique -> DcStrictness -> Unique
$cp1Hashable :: Eq DcStrictness
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
putList :: [DcStrictness] -> Put
$cputList :: [DcStrictness] -> Put
get :: Get DcStrictness
$cget :: Get DcStrictness
put :: DcStrictness -> Put
$cput :: DcStrictness -> Put
Binary)