{-|
  Copyright   :  (C) 2012-2016, University of Twente,
                          2017, Google Inc.
  License     :  BSD2 (see the file LICENSE)
  Maintainer  :  Christiaan Baaij <christiaan.baaij@gmail.com>

  Data Constructors in CoreHW
-}

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

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

import Control.DeepSeq                        (NFData(..))
import Data.Binary                            (Binary)
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
import Clash.Util

-- | 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 -> [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,Unique -> DataCon -> Unique
DataCon -> Unique
(Unique -> DataCon -> Unique)
-> (DataCon -> Unique) -> Hashable DataCon
forall a. (Unique -> a -> Unique) -> (a -> Unique) -> Hashable a
hash :: DataCon -> Unique
$chash :: DataCon -> Unique
hashWithSalt :: Unique -> DataCon -> Unique
$chashWithSalt :: Unique -> DataCon -> Unique
Hashable,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 dc :: DataCon
dc u :: 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