{-|
  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 #-}

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           GHC.Types.SrcLoc                       (SrcSpan, noSrcSpan)

import           Clash.Unique

data Name a
  = Name
  { forall a. Name a -> NameSort
nameSort :: NameSort
  , forall a. Name a -> OccName
nameOcc  :: !OccName
  , forall a. Name a -> Unique
nameUniq :: {-# UNPACK #-} !Unique
  , forall a. Name a -> SrcSpan
nameLoc  :: !SrcSpan
  }
  deriving (Int -> Name a -> ShowS
[Name a] -> ShowS
Name a -> String
(Int -> Name a -> ShowS)
-> (Name a -> String) -> ([Name a] -> ShowS) -> Show (Name a)
forall a. Int -> Name a -> ShowS
forall a. [Name a] -> ShowS
forall a. Name a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Int -> Name a -> ShowS
showsPrec :: Int -> Name a -> ShowS
$cshow :: forall a. Name a -> String
show :: Name a -> String
$cshowList :: forall a. [Name a] -> ShowS
showList :: [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
$cfrom :: forall a x. Name a -> Rep (Name a) x
from :: forall x. Name a -> Rep (Name a) x
$cto :: forall a x. Rep (Name a) x -> Name a
to :: forall x. Rep (Name a) x -> Name a
Generic,Name a -> ()
(Name a -> ()) -> NFData (Name a)
forall a. Name a -> ()
forall a. (a -> ()) -> NFData a
$crnf :: forall a. Name a -> ()
rnf :: 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
$cput :: forall a. Name a -> Put
put :: Name a -> Put
$cget :: forall a. Get (Name a)
get :: Get (Name a)
$cputList :: forall a. [Name a] -> Put
putList :: [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 :: Int -> Name a -> Int
hashWithSalt Int
salt Name a
nm = Int -> Unique -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
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=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
$c== :: NameSort -> NameSort -> Bool
== :: NameSort -> NameSort -> Bool
$c/= :: NameSort -> NameSort -> Bool
/= :: 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
$ccompare :: NameSort -> NameSort -> Ordering
compare :: NameSort -> NameSort -> Ordering
$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
>= :: NameSort -> NameSort -> Bool
$cmax :: NameSort -> NameSort -> NameSort
max :: NameSort -> NameSort -> NameSort
$cmin :: NameSort -> NameSort -> NameSort
min :: NameSort -> NameSort -> NameSort
Ord,Int -> NameSort -> ShowS
[NameSort] -> ShowS
NameSort -> String
(Int -> NameSort -> ShowS)
-> (NameSort -> String) -> ([NameSort] -> ShowS) -> Show NameSort
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NameSort -> ShowS
showsPrec :: Int -> NameSort -> ShowS
$cshow :: NameSort -> String
show :: NameSort -> String
$cshowList :: [NameSort] -> ShowS
showList :: [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
$cfrom :: forall x. NameSort -> Rep NameSort x
from :: forall x. NameSort -> Rep NameSort x
$cto :: forall x. Rep NameSort x -> NameSort
to :: forall x. Rep NameSort x -> NameSort
Generic,NameSort -> ()
(NameSort -> ()) -> NFData NameSort
forall a. (a -> ()) -> NFData a
$crnf :: NameSort -> ()
rnf :: NameSort -> ()
NFData,Eq NameSort
Eq NameSort =>
(Int -> NameSort -> Int) -> (NameSort -> Int) -> Hashable NameSort
Int -> NameSort -> Int
NameSort -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
$chashWithSalt :: Int -> NameSort -> Int
hashWithSalt :: Int -> NameSort -> Int
$chash :: NameSort -> Int
hash :: NameSort -> Int
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
$cput :: NameSort -> Put
put :: NameSort -> Put
$cget :: Get NameSort
get :: Get NameSort
$cputList :: [NameSort] -> Put
putList :: [NameSort] -> Put
Binary)

mkUnsafeName
  :: NameSort
  -> Text
  -> Unique
  -> Name a
mkUnsafeName :: forall a. 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 :: forall a. 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 :: forall a. 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 :: forall a. 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