{-# LANGUAGE CPP #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE OverloadedStrings #-}
module Clash.Netlist.Id
(
IdentifierSet
, IdentifierSetMonad(..)
, HasIdentifierSet(..)
, emptyIdentifierSet
, makeSet
, clearSet
, Identifier
, IdentifierType (..)
, unsafeMake
, unsafeFromCoreId
, toText
, toLazyText
, toList
, union
, make
, makeBasic
, makeBasicOr
, makeAs
, add
, addMultiple
, addRaw
, deepen
, deepenN
, next
, nextN
, prefix
, suffix
, fromCoreId
, VHDL.stripDollarPrefixes
, toBasicId#
, isBasic#
, isExtended#
)
where
import Clash.Annotations.Primitive (HDL (..))
import Clash.Core.Name (nameOcc)
import Clash.Core.Var (Id, varName)
import Clash.Debug (debugIsOn)
import Clash.Netlist.Types
(PreserveCase(..), HasIdentifierSet(..), IdentifierSet(..), Identifier(..),
IdentifierType(..), IdentifierSetMonad(identifierSetM))
import qualified Data.HashSet as HashSet
import qualified Data.HashMap.Strict as HashMap
import qualified Data.IntMap.Strict as IntMap
import qualified Data.List as List
import Data.Text (Text)
import qualified Data.Text.Lazy as LT
import GHC.Stack
import qualified Clash.Netlist.Id.VHDL as VHDL
import Clash.Netlist.Id.Internal
emptyIdentifierSet
:: Bool
-> PreserveCase
-> HDL
-> IdentifierSet
emptyIdentifierSet :: Bool -> PreserveCase -> HDL -> IdentifierSet
emptyIdentifierSet Bool
esc PreserveCase
lw HDL
hdl = Bool -> PreserveCase -> HDL -> HashSet Identifier -> IdentifierSet
makeSet Bool
esc PreserveCase
lw HDL
hdl HashSet Identifier
forall a. Monoid a => a
mempty
union :: HasCallStack => IdentifierSet -> IdentifierSet -> IdentifierSet
union :: IdentifierSet -> IdentifierSet -> IdentifierSet
union (IdentifierSet Bool
escL PreserveCase
lwL HDL
hdlL FreshCache
freshL HashSet Identifier
idsL) (IdentifierSet Bool
escR PreserveCase
lwR HDL
hdlR FreshCache
freshR HashSet Identifier
idsR)
| Bool
escL Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool
escR = [Char] -> IdentifierSet
forall a. HasCallStack => [Char] -> a
error ([Char] -> IdentifierSet) -> [Char] -> IdentifierSet
forall a b. (a -> b) -> a -> b
$ [Char]
"Internal error: escL /= escR, " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> (Bool, Bool) -> [Char]
forall a. Show a => a -> [Char]
show (Bool
escL, Bool
escR)
| HDL
hdlL HDL -> HDL -> Bool
forall a. Eq a => a -> a -> Bool
/= HDL
hdlR = [Char] -> IdentifierSet
forall a. HasCallStack => [Char] -> a
error ([Char] -> IdentifierSet) -> [Char] -> IdentifierSet
forall a b. (a -> b) -> a -> b
$ [Char]
"Internal error: hdlL /= hdlR, " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> (HDL, HDL) -> [Char]
forall a. Show a => a -> [Char]
show (HDL
hdlL, HDL
hdlR)
| PreserveCase
lwL PreserveCase -> PreserveCase -> Bool
forall a. Eq a => a -> a -> Bool
/= PreserveCase
lwR = [Char] -> IdentifierSet
forall a. HasCallStack => [Char] -> a
error ([Char] -> IdentifierSet) -> [Char] -> IdentifierSet
forall a b. (a -> b) -> a -> b
$ [Char]
"Internal error: lwL /= lwR , " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> (PreserveCase, PreserveCase) -> [Char]
forall a. Show a => a -> [Char]
show (PreserveCase
lwL, PreserveCase
lwR)
| Bool
otherwise = Bool
-> PreserveCase
-> HDL
-> FreshCache
-> HashSet Identifier
-> IdentifierSet
IdentifierSet Bool
escR PreserveCase
lwR HDL
hdlR FreshCache
fresh HashSet Identifier
ids
where
fresh :: FreshCache
fresh = (IntMap Word -> IntMap Word -> IntMap Word)
-> FreshCache -> FreshCache -> FreshCache
forall k v.
(Eq k, Hashable k) =>
(v -> v -> v) -> HashMap k v -> HashMap k v -> HashMap k v
HashMap.unionWith ((Word -> Word -> Word) -> IntMap Word -> IntMap Word -> IntMap Word
forall a. (a -> a -> a) -> IntMap a -> IntMap a -> IntMap a
IntMap.unionWith Word -> Word -> Word
forall a. Ord a => a -> a -> a
max) FreshCache
freshL FreshCache
freshR
ids :: HashSet Identifier
ids = HashSet Identifier -> HashSet Identifier -> HashSet Identifier
forall a. (Eq a, Hashable a) => HashSet a -> HashSet a -> HashSet a
HashSet.union HashSet Identifier
idsL HashSet Identifier
idsR
makeSet
:: Bool
-> PreserveCase
-> HDL
-> HashSet.HashSet Identifier
-> IdentifierSet
makeSet :: Bool -> PreserveCase -> HDL -> HashSet Identifier -> IdentifierSet
makeSet Bool
esc PreserveCase
lw HDL
hdl HashSet Identifier
ids = Bool
-> PreserveCase
-> HDL
-> FreshCache
-> HashSet Identifier
-> IdentifierSet
IdentifierSet Bool
esc PreserveCase
lw HDL
hdl FreshCache
fresh HashSet Identifier
ids
where
fresh :: FreshCache
fresh = (FreshCache -> Identifier -> FreshCache)
-> FreshCache -> HashSet Identifier -> FreshCache
forall (t :: Type -> Type) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' HasCallStack => FreshCache -> Identifier -> FreshCache
FreshCache -> Identifier -> FreshCache
updateFreshCache# FreshCache
forall a. Monoid a => a
mempty HashSet Identifier
ids
clearSet :: IdentifierSet -> IdentifierSet
clearSet :: IdentifierSet -> IdentifierSet
clearSet (IdentifierSet Bool
escL PreserveCase
lwL HDL
hdlL FreshCache
_ HashSet Identifier
_) =
Bool
-> PreserveCase
-> HDL
-> FreshCache
-> HashSet Identifier
-> IdentifierSet
IdentifierSet Bool
escL PreserveCase
lwL HDL
hdlL FreshCache
forall a. Monoid a => a
mempty HashSet Identifier
forall a. Monoid a => a
mempty
toList :: IdentifierSet -> [Identifier]
toList :: IdentifierSet -> [Identifier]
toList (IdentifierSet Bool
_ PreserveCase
_ HDL
_ FreshCache
_ HashSet Identifier
idStore) = HashSet Identifier -> [Identifier]
forall a. HashSet a -> [a]
HashSet.toList HashSet Identifier
idStore
toText :: Identifier -> Text
toText :: Identifier -> Text
toText = Identifier -> Text
toText#
toLazyText :: Identifier -> LT.Text
toLazyText :: Identifier -> Text
toLazyText = Text -> Text
LT.fromStrict (Text -> Text) -> (Identifier -> Text) -> Identifier -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identifier -> Text
toText
withIdentifierSetM'
:: IdentifierSetMonad m
=> (IdentifierSet -> a -> IdentifierSet)
-> a
-> m ()
withIdentifierSetM' :: (IdentifierSet -> a -> IdentifierSet) -> a -> m ()
withIdentifierSetM' IdentifierSet -> a -> IdentifierSet
f a
a = do
IdentifierSet
is0 <- (IdentifierSet -> IdentifierSet) -> m IdentifierSet
forall (m :: Type -> Type).
IdentifierSetMonad m =>
(IdentifierSet -> IdentifierSet) -> m IdentifierSet
identifierSetM IdentifierSet -> IdentifierSet
forall a. a -> a
id
(IdentifierSet -> IdentifierSet) -> m IdentifierSet
forall (m :: Type -> Type).
IdentifierSetMonad m =>
(IdentifierSet -> IdentifierSet) -> m IdentifierSet
identifierSetM (IdentifierSet -> IdentifierSet -> IdentifierSet
forall a b. a -> b -> a
const (IdentifierSet -> a -> IdentifierSet
f IdentifierSet
is0 a
a)) m IdentifierSet -> m () -> m ()
forall (m :: Type -> Type) a b. Monad m => m a -> m b -> m b
>> () -> m ()
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure ()
withIdentifierSetM
:: IdentifierSetMonad m
=> (IdentifierSet -> a -> (IdentifierSet, b))
-> a
-> m b
withIdentifierSetM :: (IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM IdentifierSet -> a -> (IdentifierSet, b)
f a
a = do
IdentifierSet
is0 <- (IdentifierSet -> IdentifierSet) -> m IdentifierSet
forall (m :: Type -> Type).
IdentifierSetMonad m =>
(IdentifierSet -> IdentifierSet) -> m IdentifierSet
identifierSetM IdentifierSet -> IdentifierSet
forall a. a -> a
id
let (IdentifierSet
is1, b
b) = IdentifierSet -> a -> (IdentifierSet, b)
f IdentifierSet
is0 a
a
IdentifierSet
_ <- (IdentifierSet -> IdentifierSet) -> m IdentifierSet
forall (m :: Type -> Type).
IdentifierSetMonad m =>
(IdentifierSet -> IdentifierSet) -> m IdentifierSet
identifierSetM (IdentifierSet -> IdentifierSet -> IdentifierSet
forall a b. a -> b -> a
const IdentifierSet
is1)
b -> m b
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure b
b
unsafeMake :: HasCallStack => Text -> Identifier
unsafeMake :: Text -> Identifier
unsafeMake Text
t =
Text -> Maybe Identifier -> CallStack -> Identifier
RawIdentifier Text
t Maybe Identifier
forall a. Maybe a
Nothing (if Bool
debugIsOn then CallStack
HasCallStack => CallStack
callStack else CallStack
emptyCallStack)
add :: HasCallStack => IdentifierSetMonad m => Identifier -> m ()
add :: Identifier -> m ()
add = (IdentifierSet -> Identifier -> IdentifierSet)
-> Identifier -> m ()
forall (m :: Type -> Type) a.
IdentifierSetMonad m =>
(IdentifierSet -> a -> IdentifierSet) -> a -> m ()
withIdentifierSetM' HasCallStack => IdentifierSet -> Identifier -> IdentifierSet
IdentifierSet -> Identifier -> IdentifierSet
add#
addMultiple :: (HasCallStack, IdentifierSetMonad m, Foldable t) => t Identifier -> m ()
addMultiple :: t Identifier -> m ()
addMultiple = (IdentifierSet -> t Identifier -> IdentifierSet)
-> t Identifier -> m ()
forall (m :: Type -> Type) a.
IdentifierSetMonad m =>
(IdentifierSet -> a -> IdentifierSet) -> a -> m ()
withIdentifierSetM' IdentifierSet -> t Identifier -> IdentifierSet
forall (t :: Type -> Type).
(HasCallStack, Foldable t) =>
IdentifierSet -> t Identifier -> IdentifierSet
addMultiple#
addRaw :: (HasCallStack, IdentifierSetMonad m) => Text -> m Identifier
addRaw :: Text -> m Identifier
addRaw = (IdentifierSet -> Text -> (IdentifierSet, Identifier))
-> Text -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM HasCallStack =>
IdentifierSet -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Text -> (IdentifierSet, Identifier)
addRaw#
make :: (HasCallStack, IdentifierSetMonad m) => Text -> m Identifier
make :: Text -> m Identifier
make = (IdentifierSet -> Text -> (IdentifierSet, Identifier))
-> Text -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM HasCallStack =>
IdentifierSet -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Text -> (IdentifierSet, Identifier)
make#
makeBasic :: (HasCallStack, IdentifierSetMonad m) => Text -> m Identifier
makeBasic :: Text -> m Identifier
makeBasic = (IdentifierSet -> Text -> (IdentifierSet, Identifier))
-> Text -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM HasCallStack =>
IdentifierSet -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Text -> (IdentifierSet, Identifier)
makeBasic#
makeBasicOr
:: (HasCallStack, IdentifierSetMonad m)
=> Text
-> Text
-> m Identifier
makeBasicOr :: Text -> Text -> m Identifier
makeBasicOr Text
hint Text
altHint =
(IdentifierSet -> (Text, Text) -> (IdentifierSet, Identifier))
-> (Text, Text) -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM
(\IdentifierSet
is0 -> (Text -> Text -> (IdentifierSet, Identifier))
-> (Text, Text) -> (IdentifierSet, Identifier)
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (HasCallStack =>
IdentifierSet -> Text -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Text -> Text -> (IdentifierSet, Identifier)
makeBasicOr# IdentifierSet
is0))
(Text
hint, Text
altHint)
makeAs :: (HasCallStack, IdentifierSetMonad m) => IdentifierType -> Text -> m Identifier
makeAs :: IdentifierType -> Text -> m Identifier
makeAs IdentifierType
Basic = Text -> m Identifier
forall (m :: Type -> Type).
(HasCallStack, IdentifierSetMonad m) =>
Text -> m Identifier
makeBasic
makeAs IdentifierType
Extended = Text -> m Identifier
forall (m :: Type -> Type).
(HasCallStack, IdentifierSetMonad m) =>
Text -> m Identifier
make
next :: (HasCallStack, IdentifierSetMonad m) => Identifier -> m Identifier
next :: Identifier -> m Identifier
next = (IdentifierSet -> Identifier -> (IdentifierSet, Identifier))
-> Identifier -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM HasCallStack =>
IdentifierSet -> Identifier -> (IdentifierSet, Identifier)
IdentifierSet -> Identifier -> (IdentifierSet, Identifier)
next#
nextN :: (HasCallStack, IdentifierSetMonad m) => Int -> Identifier -> m [Identifier]
nextN :: Int -> Identifier -> m [Identifier]
nextN Int
n = (IdentifierSet -> Identifier -> (IdentifierSet, [Identifier]))
-> Identifier -> m [Identifier]
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM (HasCallStack =>
Int -> IdentifierSet -> Identifier -> (IdentifierSet, [Identifier])
Int -> IdentifierSet -> Identifier -> (IdentifierSet, [Identifier])
nextN# Int
n)
deepen :: (HasCallStack, IdentifierSetMonad m) => Identifier -> m Identifier
deepen :: Identifier -> m Identifier
deepen = (IdentifierSet -> Identifier -> (IdentifierSet, Identifier))
-> Identifier -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM HasCallStack =>
IdentifierSet -> Identifier -> (IdentifierSet, Identifier)
IdentifierSet -> Identifier -> (IdentifierSet, Identifier)
deepen#
deepenN :: (HasCallStack, IdentifierSetMonad m) => Int -> Identifier -> m [Identifier]
deepenN :: Int -> Identifier -> m [Identifier]
deepenN Int
n = (IdentifierSet -> Identifier -> (IdentifierSet, [Identifier]))
-> Identifier -> m [Identifier]
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM (HasCallStack =>
Int -> IdentifierSet -> Identifier -> (IdentifierSet, [Identifier])
Int -> IdentifierSet -> Identifier -> (IdentifierSet, [Identifier])
deepenN# Int
n)
suffix :: (HasCallStack, IdentifierSetMonad m) => Identifier -> Text -> m Identifier
suffix :: Identifier -> Text -> m Identifier
suffix Identifier
id0 Text
suffix_ = (IdentifierSet -> Identifier -> (IdentifierSet, Identifier))
-> Identifier -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM (\IdentifierSet
is Identifier
id1 -> HasCallStack =>
IdentifierSet -> Identifier -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Identifier -> Text -> (IdentifierSet, Identifier)
suffix# IdentifierSet
is Identifier
id1 Text
suffix_) Identifier
id0
prefix :: (HasCallStack, IdentifierSetMonad m) => Identifier -> Text -> m Identifier
prefix :: Identifier -> Text -> m Identifier
prefix Identifier
id0 Text
prefix_ = (IdentifierSet -> Identifier -> (IdentifierSet, Identifier))
-> Identifier -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM (\IdentifierSet
is Identifier
id1 -> HasCallStack =>
IdentifierSet -> Identifier -> Text -> (IdentifierSet, Identifier)
IdentifierSet -> Identifier -> Text -> (IdentifierSet, Identifier)
prefix# IdentifierSet
is Identifier
id1 Text
prefix_) Identifier
id0
fromCoreId :: (HasCallStack, IdentifierSetMonad m) => Id -> m Identifier
fromCoreId :: Id -> m Identifier
fromCoreId = (IdentifierSet -> Id -> (IdentifierSet, Identifier))
-> Id -> m Identifier
forall (m :: Type -> Type) a b.
IdentifierSetMonad m =>
(IdentifierSet -> a -> (IdentifierSet, b)) -> a -> m b
withIdentifierSetM IdentifierSet -> Id -> (IdentifierSet, Identifier)
fromCoreId#
unsafeFromCoreId :: HasCallStack => Id -> Identifier
unsafeFromCoreId :: Id -> Identifier
unsafeFromCoreId = HasCallStack => Text -> Identifier
Text -> Identifier
unsafeMake (Text -> Identifier) -> (Id -> Text) -> Id -> Identifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name Term -> Text
forall a. Name a -> Text
nameOcc (Name Term -> Text) -> (Id -> Name Term) -> Id -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id -> Name Term
forall a. Var a -> Name a
varName