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

  Names
-}

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

module Clash.Core.Name
  ( module Clash.Core.Name
  , noSrcSpan
  )
where

import           Control.DeepSeq                        (NFData)
import           Data.Binary                            (Binary)
import           Data.Function                          (on)
import           Data.Hashable                          (Hashable (..))
import           Data.Text                              (Text, append)
import           GHC.BasicTypes.Extra                   ()
import           GHC.Generics                           (Generic)
import           GHC.SrcLoc.Extra                       ()
#if MIN_VERSION_ghc(9,0,0)
import           GHC.Types.SrcLoc                       (SrcSpan, noSrcSpan)
#else
import           SrcLoc                                 (SrcSpan, noSrcSpan)
#endif

import           Clash.Unique

data Name a
  = Name
  { Name a -> NameSort
nameSort :: NameSort
  , Name a -> OccName
nameOcc  :: !OccName
  , Name a -> Unique
nameUniq :: {-# UNPACK #-} !Unique
  , Name a -> SrcSpan
nameLoc  :: !SrcSpan
  }
  deriving (Unique -> Name a -> ShowS
[Name a] -> ShowS
Name a -> String
(Unique -> Name a -> ShowS)
-> (Name a -> String) -> ([Name a] -> ShowS) -> Show (Name a)
forall a. Unique -> Name a -> ShowS
forall a. [Name a] -> ShowS
forall a. Name a -> String
forall a.
(Unique -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Name a] -> ShowS
$cshowList :: forall a. [Name a] -> ShowS
show :: Name a -> String
$cshow :: forall a. Name a -> String
showsPrec :: Unique -> Name a -> ShowS
$cshowsPrec :: forall a. Unique -> Name a -> ShowS
Show,(forall x. Name a -> Rep (Name a) x)
-> (forall x. Rep (Name a) x -> Name a) -> Generic (Name a)
forall x. Rep (Name a) x -> Name a
forall x. Name a -> Rep (Name a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Name a) x -> Name a
forall a x. Name a -> Rep (Name a) x
$cto :: forall a x. Rep (Name a) x -> Name a
$cfrom :: forall a x. Name a -> Rep (Name a) x
Generic,Name a -> ()
(Name a -> ()) -> NFData (Name a)
forall a. Name a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Name a -> ()
$crnf :: forall a. Name a -> ()
NFData,Get (Name a)
[Name a] -> Put
Name a -> Put
(Name a -> Put)
-> Get (Name a) -> ([Name a] -> Put) -> Binary (Name a)
forall a. Get (Name a)
forall a. [Name a] -> Put
forall a. Name a -> Put
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Name a] -> Put
$cputList :: forall a. [Name a] -> Put
get :: Get (Name a)
$cget :: forall a. Get (Name a)
put :: Name a -> Put
$cput :: forall a. Name a -> Put
Binary)

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

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

instance Hashable (Name a) where
  hashWithSalt :: Unique -> Name a -> Unique
hashWithSalt Unique
salt Name a
nm = Unique -> Unique -> Unique
forall a. Hashable a => Unique -> a -> Unique
hashWithSalt Unique
salt (Name a -> Unique
forall a. Name a -> Unique
nameUniq Name a
nm)

instance Uniquable (Name a) where
  getUnique :: Name a -> Unique
getUnique = Name a -> Unique
forall a. Name a -> Unique
nameUniq
  setUnique :: Name a -> Unique -> Name a
setUnique Name a
nm Unique
u = Name a
nm {nameUniq :: Unique
nameUniq=Unique
u}

type OccName = Text

data NameSort
  = User
  | System
  | Internal
  deriving (NameSort -> NameSort -> Bool
(NameSort -> NameSort -> Bool)
-> (NameSort -> NameSort -> Bool) -> Eq NameSort
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NameSort -> NameSort -> Bool
$c/= :: NameSort -> NameSort -> Bool
== :: NameSort -> NameSort -> Bool
$c== :: NameSort -> NameSort -> Bool
Eq,Eq NameSort
Eq NameSort
-> (NameSort -> NameSort -> Ordering)
-> (NameSort -> NameSort -> Bool)
-> (NameSort -> NameSort -> Bool)
-> (NameSort -> NameSort -> Bool)
-> (NameSort -> NameSort -> Bool)
-> (NameSort -> NameSort -> NameSort)
-> (NameSort -> NameSort -> NameSort)
-> Ord NameSort
NameSort -> NameSort -> Bool
NameSort -> NameSort -> Ordering
NameSort -> NameSort -> NameSort
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 :: NameSort -> NameSort -> NameSort
$cmin :: NameSort -> NameSort -> NameSort
max :: NameSort -> NameSort -> NameSort
$cmax :: NameSort -> NameSort -> NameSort
>= :: NameSort -> NameSort -> Bool
$c>= :: NameSort -> NameSort -> Bool
> :: NameSort -> NameSort -> Bool
$c> :: NameSort -> NameSort -> Bool
<= :: NameSort -> NameSort -> Bool
$c<= :: NameSort -> NameSort -> Bool
< :: NameSort -> NameSort -> Bool
$c< :: NameSort -> NameSort -> Bool
compare :: NameSort -> NameSort -> Ordering
$ccompare :: NameSort -> NameSort -> Ordering
$cp1Ord :: Eq NameSort
Ord,Unique -> NameSort -> ShowS
[NameSort] -> ShowS
NameSort -> String
(Unique -> NameSort -> ShowS)
-> (NameSort -> String) -> ([NameSort] -> ShowS) -> Show NameSort
forall a.
(Unique -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NameSort] -> ShowS
$cshowList :: [NameSort] -> ShowS
show :: NameSort -> String
$cshow :: NameSort -> String
showsPrec :: Unique -> NameSort -> ShowS
$cshowsPrec :: Unique -> NameSort -> ShowS
Show,(forall x. NameSort -> Rep NameSort x)
-> (forall x. Rep NameSort x -> NameSort) -> Generic NameSort
forall x. Rep NameSort x -> NameSort
forall x. NameSort -> Rep NameSort x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep NameSort x -> NameSort
$cfrom :: forall x. NameSort -> Rep NameSort x
Generic,NameSort -> ()
(NameSort -> ()) -> NFData NameSort
forall a. (a -> ()) -> NFData a
rnf :: NameSort -> ()
$crnf :: NameSort -> ()
NFData,Eq NameSort
Eq NameSort
-> (Unique -> NameSort -> Unique)
-> (NameSort -> Unique)
-> Hashable NameSort
Unique -> NameSort -> Unique
NameSort -> Unique
forall a.
Eq a -> (Unique -> a -> Unique) -> (a -> Unique) -> Hashable a
hash :: NameSort -> Unique
$chash :: NameSort -> Unique
hashWithSalt :: Unique -> NameSort -> Unique
$chashWithSalt :: Unique -> NameSort -> Unique
$cp1Hashable :: Eq NameSort
Hashable,Get NameSort
[NameSort] -> Put
NameSort -> Put
(NameSort -> Put)
-> Get NameSort -> ([NameSort] -> Put) -> Binary NameSort
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [NameSort] -> Put
$cputList :: [NameSort] -> Put
get :: Get NameSort
$cget :: Get NameSort
put :: NameSort -> Put
$cput :: NameSort -> Put
Binary)

mkUnsafeName
  :: NameSort
  -> Text
  -> Unique
  -> Name a
mkUnsafeName :: NameSort -> OccName -> Unique -> Name a
mkUnsafeName NameSort
ns OccName
s Unique
i = NameSort -> OccName -> Unique -> SrcSpan -> Name a
forall a. NameSort -> OccName -> Unique -> SrcSpan -> Name a
Name NameSort
ns OccName
s Unique
i SrcSpan
noSrcSpan

mkUnsafeSystemName
  :: Text
  -> Unique
  -> Name a
mkUnsafeSystemName :: OccName -> Unique -> Name a
mkUnsafeSystemName OccName
s Unique
i = NameSort -> OccName -> Unique -> SrcSpan -> Name a
forall a. NameSort -> OccName -> Unique -> SrcSpan -> Name a
Name NameSort
System OccName
s Unique
i SrcSpan
noSrcSpan

mkUnsafeInternalName
  :: Text
  -> Unique
  -> Name a
mkUnsafeInternalName :: OccName -> Unique -> Name a
mkUnsafeInternalName OccName
s Unique
i = NameSort -> OccName -> Unique -> SrcSpan -> Name a
forall a. NameSort -> OccName -> Unique -> SrcSpan -> Name a
Name NameSort
Internal (OccName
"c$" OccName -> OccName -> OccName
`append` OccName
s) Unique
i SrcSpan
noSrcSpan

appendToName :: Name a -> Text -> Name a
appendToName :: Name a -> OccName -> Name a
appendToName (Name NameSort
sort OccName
nm Unique
uniq SrcSpan
loc) OccName
s = NameSort -> OccName -> Unique -> SrcSpan -> Name a
forall a. NameSort -> OccName -> Unique -> SrcSpan -> Name a
Name NameSort
Internal OccName
nm2 Unique
uniq SrcSpan
loc
  where
    nm1 :: OccName
nm1 = case NameSort
sort of {NameSort
Internal -> OccName
nm; NameSort
_ -> OccName
"c$" OccName -> OccName -> OccName
`append` OccName
nm}
    nm2 :: OccName
nm2 = OccName
nm1 OccName -> OccName -> OccName
`append` OccName
s