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

  Names
-}

{-# LANGUAGE DeriveAnyClass        #-}
{-# LANGUAGE DeriveGeneric         #-}
{-# 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                       ()
import           SrcLoc                                 (SrcSpan, noSrcSpan)

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 salt :: Unique
salt nm :: 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

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

mkUnsafeSystemName
  :: Text
  -> Unique
  -> Name a
mkUnsafeSystemName :: OccName -> Unique -> Name a
mkUnsafeSystemName s :: OccName
s i :: 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 s :: OccName
s i :: Unique
i = NameSort -> OccName -> Unique -> SrcSpan -> Name a
forall a. NameSort -> OccName -> Unique -> SrcSpan -> Name a
Name NameSort
Internal ("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 sort :: NameSort
sort nm :: OccName
nm uniq :: Unique
uniq loc :: SrcSpan
loc) s :: 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 {Internal -> OccName
nm; _ -> "c$" OccName -> OccName -> OccName
`append` OccName
nm}
    nm2 :: OccName
nm2 = OccName
nm1 OccName -> OccName -> OccName
`append` OccName
s