{-# LANGUAGE DefaultSignatures      #-}
{-# LANGUAGE DeriveAnyClass         #-}
{-# LANGUAGE FlexibleInstances      #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE OverloadedStrings      #-}

module PlutusCore.Name
    ( -- * Types
      Name (..)
    , TyName (..)
    , Unique (..)
    , TypeUnique (..)
    , TermUnique (..)
    , HasUnique (..)
    , theUnique
    , UniqueMap (..)
    -- * Functions
    , insertByUnique
    , insertByName
    , insertByNameIndex
    , fromFoldable
    , fromUniques
    , fromNames
    , lookupUnique
    , lookupName
    , lookupNameIndex
    , mapNameString
    , mapTyNameString
    , isEmpty
    ) where

import PlutusPrelude

import PlutusCore.Pretty.ConfigName

import Control.Lens
import Data.Hashable
import Data.IntMap.Strict qualified as IM
import Data.Text qualified as T
import Instances.TH.Lift ()
import Language.Haskell.TH.Syntax (Lift)

-- | A 'Name' represents variables/names in Plutus Core.
data Name = Name
    { Name -> Text
nameString :: T.Text -- ^ The identifier name, for use in error messages.
    , Name -> Unique
nameUnique :: Unique -- ^ A 'Unique' assigned to the name, allowing for cheap comparisons in the compiler.
    }
    deriving stock (Int -> Name -> ShowS
[Name] -> ShowS
Name -> String
(Int -> Name -> ShowS)
-> (Name -> String) -> ([Name] -> ShowS) -> Show Name
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Name] -> ShowS
$cshowList :: [Name] -> ShowS
show :: Name -> String
$cshow :: Name -> String
showsPrec :: Int -> Name -> ShowS
$cshowsPrec :: Int -> Name -> ShowS
Show, (forall x. Name -> Rep Name x)
-> (forall x. Rep Name x -> Name) -> Generic Name
forall x. Rep Name x -> Name
forall x. Name -> Rep Name x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Name x -> Name
$cfrom :: forall x. Name -> Rep Name x
Generic, Name -> Q Exp
Name -> Q (TExp Name)
(Name -> Q Exp) -> (Name -> Q (TExp Name)) -> Lift Name
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: Name -> Q (TExp Name)
$cliftTyped :: Name -> Q (TExp Name)
lift :: Name -> Q Exp
$clift :: Name -> Q Exp
Lift)
    deriving anyclass (Name -> ()
(Name -> ()) -> NFData Name
forall a. (a -> ()) -> NFData a
rnf :: Name -> ()
$crnf :: Name -> ()
NFData, Int -> Name -> Int
Name -> Int
(Int -> Name -> Int) -> (Name -> Int) -> Hashable Name
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Name -> Int
$chash :: Name -> Int
hashWithSalt :: Int -> Name -> Int
$chashWithSalt :: Int -> Name -> Int
Hashable)

-- | We use a @newtype@ to enforce separation between names used for types and
-- those used for terms.
newtype TyName = TyName { TyName -> Name
unTyName :: Name }
    deriving stock (Int -> TyName -> ShowS
[TyName] -> ShowS
TyName -> String
(Int -> TyName -> ShowS)
-> (TyName -> String) -> ([TyName] -> ShowS) -> Show TyName
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TyName] -> ShowS
$cshowList :: [TyName] -> ShowS
show :: TyName -> String
$cshow :: TyName -> String
showsPrec :: Int -> TyName -> ShowS
$cshowsPrec :: Int -> TyName -> ShowS
Show, (forall x. TyName -> Rep TyName x)
-> (forall x. Rep TyName x -> TyName) -> Generic TyName
forall x. Rep TyName x -> TyName
forall x. TyName -> Rep TyName x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep TyName x -> TyName
$cfrom :: forall x. TyName -> Rep TyName x
Generic, TyName -> Q Exp
TyName -> Q (TExp TyName)
(TyName -> Q Exp) -> (TyName -> Q (TExp TyName)) -> Lift TyName
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: TyName -> Q (TExp TyName)
$cliftTyped :: TyName -> Q (TExp TyName)
lift :: TyName -> Q Exp
$clift :: TyName -> Q Exp
Lift)
    deriving newtype (TyName -> TyName -> Bool
(TyName -> TyName -> Bool)
-> (TyName -> TyName -> Bool) -> Eq TyName
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TyName -> TyName -> Bool
$c/= :: TyName -> TyName -> Bool
== :: TyName -> TyName -> Bool
$c== :: TyName -> TyName -> Bool
Eq, Eq TyName
Eq TyName
-> (TyName -> TyName -> Ordering)
-> (TyName -> TyName -> Bool)
-> (TyName -> TyName -> Bool)
-> (TyName -> TyName -> Bool)
-> (TyName -> TyName -> Bool)
-> (TyName -> TyName -> TyName)
-> (TyName -> TyName -> TyName)
-> Ord TyName
TyName -> TyName -> Bool
TyName -> TyName -> Ordering
TyName -> TyName -> TyName
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 :: TyName -> TyName -> TyName
$cmin :: TyName -> TyName -> TyName
max :: TyName -> TyName -> TyName
$cmax :: TyName -> TyName -> TyName
>= :: TyName -> TyName -> Bool
$c>= :: TyName -> TyName -> Bool
> :: TyName -> TyName -> Bool
$c> :: TyName -> TyName -> Bool
<= :: TyName -> TyName -> Bool
$c<= :: TyName -> TyName -> Bool
< :: TyName -> TyName -> Bool
$c< :: TyName -> TyName -> Bool
compare :: TyName -> TyName -> Ordering
$ccompare :: TyName -> TyName -> Ordering
$cp1Ord :: Eq TyName
Ord, TyName -> ()
(TyName -> ()) -> NFData TyName
forall a. (a -> ()) -> NFData a
rnf :: TyName -> ()
$crnf :: TyName -> ()
NFData, Int -> TyName -> Int
TyName -> Int
(Int -> TyName -> Int) -> (TyName -> Int) -> Hashable TyName
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TyName -> Int
$chash :: TyName -> Int
hashWithSalt :: Int -> TyName -> Int
$chashWithSalt :: Int -> TyName -> Int
Hashable, PrettyBy config)
instance Wrapped TyName

instance HasPrettyConfigName config => PrettyBy config Name where
    prettyBy :: config -> Name -> Doc ann
prettyBy config
config (Name Text
txt (Unique Int
uniq))
        | Bool
showsUnique = Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
txt Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Doc ann
"_" Doc ann -> Doc ann -> Doc ann
forall a. Semigroup a => a -> a -> a
<> Int -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Int
uniq
        | Bool
otherwise   = Text -> Doc ann
forall a ann. Pretty a => a -> Doc ann
pretty Text
txt
        where PrettyConfigName Bool
showsUnique = config -> PrettyConfigName
forall config.
HasPrettyConfigName config =>
config -> PrettyConfigName
toPrettyConfigName config
config

-- | Apply a function to the string representation of a 'Name'.
mapNameString :: (T.Text -> T.Text) -> Name -> Name
mapNameString :: (Text -> Text) -> Name -> Name
mapNameString Text -> Text
f Name
name = Name
name { nameString :: Text
nameString = Text -> Text
f (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Name -> Text
nameString Name
name }

-- | Apply a function to the string representation of a 'TyName'.
mapTyNameString :: (T.Text -> T.Text) -> TyName -> TyName
mapTyNameString :: (Text -> Text) -> TyName -> TyName
mapTyNameString Text -> Text
f (TyName Name
name) = Name -> TyName
TyName (Name -> TyName) -> Name -> TyName
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> Name -> Name
mapNameString Text -> Text
f Name
name

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

instance Ord Name where
    <= :: Name -> Name -> Bool
(<=) = Unique -> Unique -> Bool
forall a. Ord a => a -> a -> Bool
(<=) (Unique -> Unique -> Bool)
-> (Name -> Unique) -> Name -> Name -> Bool
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` Name -> Unique
nameUnique

-- | A unique identifier
newtype Unique = Unique { Unique -> Int
unUnique :: Int }
    deriving stock (Unique -> Unique -> Bool
(Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool) -> Eq Unique
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Unique -> Unique -> Bool
$c/= :: Unique -> Unique -> Bool
== :: Unique -> Unique -> Bool
$c== :: Unique -> Unique -> Bool
Eq, Int -> Unique -> ShowS
[Unique] -> ShowS
Unique -> String
(Int -> Unique -> ShowS)
-> (Unique -> String) -> ([Unique] -> ShowS) -> Show Unique
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Unique] -> ShowS
$cshowList :: [Unique] -> ShowS
show :: Unique -> String
$cshow :: Unique -> String
showsPrec :: Int -> Unique -> ShowS
$cshowsPrec :: Int -> Unique -> ShowS
Show, Eq Unique
Eq Unique
-> (Unique -> Unique -> Ordering)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Bool)
-> (Unique -> Unique -> Unique)
-> (Unique -> Unique -> Unique)
-> Ord Unique
Unique -> Unique -> Bool
Unique -> Unique -> Ordering
Unique -> Unique -> Unique
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 :: Unique -> Unique -> Unique
$cmin :: Unique -> Unique -> Unique
max :: Unique -> Unique -> Unique
$cmax :: Unique -> Unique -> Unique
>= :: Unique -> Unique -> Bool
$c>= :: Unique -> Unique -> Bool
> :: Unique -> Unique -> Bool
$c> :: Unique -> Unique -> Bool
<= :: Unique -> Unique -> Bool
$c<= :: Unique -> Unique -> Bool
< :: Unique -> Unique -> Bool
$c< :: Unique -> Unique -> Bool
compare :: Unique -> Unique -> Ordering
$ccompare :: Unique -> Unique -> Ordering
$cp1Ord :: Eq Unique
Ord, Unique -> Q Exp
Unique -> Q (TExp Unique)
(Unique -> Q Exp) -> (Unique -> Q (TExp Unique)) -> Lift Unique
forall t. (t -> Q Exp) -> (t -> Q (TExp t)) -> Lift t
liftTyped :: Unique -> Q (TExp Unique)
$cliftTyped :: Unique -> Q (TExp Unique)
lift :: Unique -> Q Exp
$clift :: Unique -> Q Exp
Lift)
    deriving newtype (Int -> Unique
Unique -> Int
Unique -> [Unique]
Unique -> Unique
Unique -> Unique -> [Unique]
Unique -> Unique -> Unique -> [Unique]
(Unique -> Unique)
-> (Unique -> Unique)
-> (Int -> Unique)
-> (Unique -> Int)
-> (Unique -> [Unique])
-> (Unique -> Unique -> [Unique])
-> (Unique -> Unique -> [Unique])
-> (Unique -> Unique -> Unique -> [Unique])
-> Enum Unique
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Unique -> Unique -> Unique -> [Unique]
$cenumFromThenTo :: Unique -> Unique -> Unique -> [Unique]
enumFromTo :: Unique -> Unique -> [Unique]
$cenumFromTo :: Unique -> Unique -> [Unique]
enumFromThen :: Unique -> Unique -> [Unique]
$cenumFromThen :: Unique -> Unique -> [Unique]
enumFrom :: Unique -> [Unique]
$cenumFrom :: Unique -> [Unique]
fromEnum :: Unique -> Int
$cfromEnum :: Unique -> Int
toEnum :: Int -> Unique
$ctoEnum :: Int -> Unique
pred :: Unique -> Unique
$cpred :: Unique -> Unique
succ :: Unique -> Unique
$csucc :: Unique -> Unique
Enum, Unique -> ()
(Unique -> ()) -> NFData Unique
forall a. (a -> ()) -> NFData a
rnf :: Unique -> ()
$crnf :: Unique -> ()
NFData, [Unique] -> Doc ann
Unique -> Doc ann
(forall ann. Unique -> Doc ann)
-> (forall ann. [Unique] -> Doc ann) -> Pretty Unique
forall ann. [Unique] -> Doc ann
forall ann. Unique -> Doc ann
forall a.
(forall ann. a -> Doc ann)
-> (forall ann. [a] -> Doc ann) -> Pretty a
prettyList :: [Unique] -> Doc ann
$cprettyList :: forall ann. [Unique] -> Doc ann
pretty :: Unique -> Doc ann
$cpretty :: forall ann. Unique -> Doc ann
Pretty, Int -> Unique -> Int
Unique -> Int
(Int -> Unique -> Int) -> (Unique -> Int) -> Hashable Unique
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Unique -> Int
$chash :: Unique -> Int
hashWithSalt :: Int -> Unique -> Int
$chashWithSalt :: Int -> Unique -> Int
Hashable)

-- | The unique of a type-level name.
newtype TypeUnique = TypeUnique
    { TypeUnique -> Unique
unTypeUnique :: Unique
    } deriving stock (TypeUnique -> TypeUnique -> Bool
(TypeUnique -> TypeUnique -> Bool)
-> (TypeUnique -> TypeUnique -> Bool) -> Eq TypeUnique
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TypeUnique -> TypeUnique -> Bool
$c/= :: TypeUnique -> TypeUnique -> Bool
== :: TypeUnique -> TypeUnique -> Bool
$c== :: TypeUnique -> TypeUnique -> Bool
Eq, Eq TypeUnique
Eq TypeUnique
-> (TypeUnique -> TypeUnique -> Ordering)
-> (TypeUnique -> TypeUnique -> Bool)
-> (TypeUnique -> TypeUnique -> Bool)
-> (TypeUnique -> TypeUnique -> Bool)
-> (TypeUnique -> TypeUnique -> Bool)
-> (TypeUnique -> TypeUnique -> TypeUnique)
-> (TypeUnique -> TypeUnique -> TypeUnique)
-> Ord TypeUnique
TypeUnique -> TypeUnique -> Bool
TypeUnique -> TypeUnique -> Ordering
TypeUnique -> TypeUnique -> TypeUnique
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 :: TypeUnique -> TypeUnique -> TypeUnique
$cmin :: TypeUnique -> TypeUnique -> TypeUnique
max :: TypeUnique -> TypeUnique -> TypeUnique
$cmax :: TypeUnique -> TypeUnique -> TypeUnique
>= :: TypeUnique -> TypeUnique -> Bool
$c>= :: TypeUnique -> TypeUnique -> Bool
> :: TypeUnique -> TypeUnique -> Bool
$c> :: TypeUnique -> TypeUnique -> Bool
<= :: TypeUnique -> TypeUnique -> Bool
$c<= :: TypeUnique -> TypeUnique -> Bool
< :: TypeUnique -> TypeUnique -> Bool
$c< :: TypeUnique -> TypeUnique -> Bool
compare :: TypeUnique -> TypeUnique -> Ordering
$ccompare :: TypeUnique -> TypeUnique -> Ordering
$cp1Ord :: Eq TypeUnique
Ord)
    deriving newtype Int -> TypeUnique -> Int
TypeUnique -> Int
(Int -> TypeUnique -> Int)
-> (TypeUnique -> Int) -> Hashable TypeUnique
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TypeUnique -> Int
$chash :: TypeUnique -> Int
hashWithSalt :: Int -> TypeUnique -> Int
$chashWithSalt :: Int -> TypeUnique -> Int
Hashable

-- | The unique of a term-level name.
newtype TermUnique = TermUnique
    { TermUnique -> Unique
unTermUnique :: Unique
    } deriving stock (TermUnique -> TermUnique -> Bool
(TermUnique -> TermUnique -> Bool)
-> (TermUnique -> TermUnique -> Bool) -> Eq TermUnique
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TermUnique -> TermUnique -> Bool
$c/= :: TermUnique -> TermUnique -> Bool
== :: TermUnique -> TermUnique -> Bool
$c== :: TermUnique -> TermUnique -> Bool
Eq, Eq TermUnique
Eq TermUnique
-> (TermUnique -> TermUnique -> Ordering)
-> (TermUnique -> TermUnique -> Bool)
-> (TermUnique -> TermUnique -> Bool)
-> (TermUnique -> TermUnique -> Bool)
-> (TermUnique -> TermUnique -> Bool)
-> (TermUnique -> TermUnique -> TermUnique)
-> (TermUnique -> TermUnique -> TermUnique)
-> Ord TermUnique
TermUnique -> TermUnique -> Bool
TermUnique -> TermUnique -> Ordering
TermUnique -> TermUnique -> TermUnique
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 :: TermUnique -> TermUnique -> TermUnique
$cmin :: TermUnique -> TermUnique -> TermUnique
max :: TermUnique -> TermUnique -> TermUnique
$cmax :: TermUnique -> TermUnique -> TermUnique
>= :: TermUnique -> TermUnique -> Bool
$c>= :: TermUnique -> TermUnique -> Bool
> :: TermUnique -> TermUnique -> Bool
$c> :: TermUnique -> TermUnique -> Bool
<= :: TermUnique -> TermUnique -> Bool
$c<= :: TermUnique -> TermUnique -> Bool
< :: TermUnique -> TermUnique -> Bool
$c< :: TermUnique -> TermUnique -> Bool
compare :: TermUnique -> TermUnique -> Ordering
$ccompare :: TermUnique -> TermUnique -> Ordering
$cp1Ord :: Eq TermUnique
Ord)
    deriving newtype Int -> TermUnique -> Int
TermUnique -> Int
(Int -> TermUnique -> Int)
-> (TermUnique -> Int) -> Hashable TermUnique
forall a. (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: TermUnique -> Int
$chash :: TermUnique -> Int
hashWithSalt :: Int -> TermUnique -> Int
$chashWithSalt :: Int -> TermUnique -> Int
Hashable

-- | Types which have a 'Unique' attached to them, mostly names.
class Coercible unique Unique => HasUnique a unique | a -> unique where
    unique :: Lens' a unique
    -- | The default implementation of 'HasUnique' for newtypes.
    default unique
        :: (Wrapped a, HasUnique (Unwrapped a) unique', Coercible unique' unique)
        => Lens' a unique
    unique = (Unwrapped a -> f (Unwrapped a)) -> a -> f a
forall s. Wrapped s => Iso' s (Unwrapped s)
_Wrapped' ((Unwrapped a -> f (Unwrapped a)) -> a -> f a)
-> ((unique -> f unique) -> Unwrapped a -> f (Unwrapped a))
-> (unique -> f unique)
-> a
-> f a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (unique' -> f unique') -> Unwrapped a -> f (Unwrapped a)
forall a unique. HasUnique a unique => Lens' a unique
unique ((unique' -> f unique') -> Unwrapped a -> f (Unwrapped a))
-> ((unique -> f unique) -> unique' -> f unique')
-> (unique -> f unique)
-> Unwrapped a
-> f (Unwrapped a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (unique -> f unique) -> unique' -> f unique'
forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
coerced

instance HasUnique Unique Unique where
    unique :: (Unique -> f Unique) -> Unique -> f Unique
unique = (Unique -> f Unique) -> Unique -> f Unique
forall a. a -> a
id

instance HasUnique Name TermUnique where
    unique :: (TermUnique -> f TermUnique) -> Name -> f Name
unique = (Name -> TermUnique)
-> (Name -> TermUnique -> Name) -> Lens' Name TermUnique
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens Name -> TermUnique
g Name -> TermUnique -> Name
s where
        g :: Name -> TermUnique
g = Unique -> TermUnique
TermUnique (Unique -> TermUnique) -> (Name -> Unique) -> Name -> TermUnique
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Unique
nameUnique
        s :: Name -> TermUnique -> Name
s Name
n (TermUnique Unique
u) = Name
n{nameUnique :: Unique
nameUnique=Unique
u}

instance HasUnique TyName TypeUnique

-- | A lens focused on the 'Unique' of a name.
theUnique :: HasUnique name unique => Lens' name Unique
theUnique :: Lens' name Unique
theUnique = (unique -> f unique) -> name -> f name
forall a unique. HasUnique a unique => Lens' a unique
unique ((unique -> f unique) -> name -> f name)
-> ((Unique -> f Unique) -> unique -> f unique)
-> (Unique -> f Unique)
-> name
-> f name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Unique -> f Unique) -> unique -> f unique
forall s t a b. (Coercible s a, Coercible t b) => Iso s t a b
coerced

-- | A mapping from uniques to values of type @a@.
newtype UniqueMap unique a = UniqueMap
    { UniqueMap unique a -> IntMap a
unUniqueMap :: IM.IntMap a
    } deriving newtype (Int -> UniqueMap unique a -> ShowS
[UniqueMap unique a] -> ShowS
UniqueMap unique a -> String
(Int -> UniqueMap unique a -> ShowS)
-> (UniqueMap unique a -> String)
-> ([UniqueMap unique a] -> ShowS)
-> Show (UniqueMap unique a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall unique a. Show a => Int -> UniqueMap unique a -> ShowS
forall unique a. Show a => [UniqueMap unique a] -> ShowS
forall unique a. Show a => UniqueMap unique a -> String
showList :: [UniqueMap unique a] -> ShowS
$cshowList :: forall unique a. Show a => [UniqueMap unique a] -> ShowS
show :: UniqueMap unique a -> String
$cshow :: forall unique a. Show a => UniqueMap unique a -> String
showsPrec :: Int -> UniqueMap unique a -> ShowS
$cshowsPrec :: forall unique a. Show a => Int -> UniqueMap unique a -> ShowS
Show, UniqueMap unique a -> UniqueMap unique a -> Bool
(UniqueMap unique a -> UniqueMap unique a -> Bool)
-> (UniqueMap unique a -> UniqueMap unique a -> Bool)
-> Eq (UniqueMap unique a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall unique a.
Eq a =>
UniqueMap unique a -> UniqueMap unique a -> Bool
/= :: UniqueMap unique a -> UniqueMap unique a -> Bool
$c/= :: forall unique a.
Eq a =>
UniqueMap unique a -> UniqueMap unique a -> Bool
== :: UniqueMap unique a -> UniqueMap unique a -> Bool
$c== :: forall unique a.
Eq a =>
UniqueMap unique a -> UniqueMap unique a -> Bool
Eq, b -> UniqueMap unique a -> UniqueMap unique a
NonEmpty (UniqueMap unique a) -> UniqueMap unique a
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
(UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a)
-> (NonEmpty (UniqueMap unique a) -> UniqueMap unique a)
-> (forall b.
    Integral b =>
    b -> UniqueMap unique a -> UniqueMap unique a)
-> Semigroup (UniqueMap unique a)
forall b.
Integral b =>
b -> UniqueMap unique a -> UniqueMap unique a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall unique a.
NonEmpty (UniqueMap unique a) -> UniqueMap unique a
forall unique a.
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
forall unique a b.
Integral b =>
b -> UniqueMap unique a -> UniqueMap unique a
stimes :: b -> UniqueMap unique a -> UniqueMap unique a
$cstimes :: forall unique a b.
Integral b =>
b -> UniqueMap unique a -> UniqueMap unique a
sconcat :: NonEmpty (UniqueMap unique a) -> UniqueMap unique a
$csconcat :: forall unique a.
NonEmpty (UniqueMap unique a) -> UniqueMap unique a
<> :: UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
$c<> :: forall unique a.
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
Semigroup, Semigroup (UniqueMap unique a)
UniqueMap unique a
Semigroup (UniqueMap unique a)
-> UniqueMap unique a
-> (UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a)
-> ([UniqueMap unique a] -> UniqueMap unique a)
-> Monoid (UniqueMap unique a)
[UniqueMap unique a] -> UniqueMap unique a
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall unique a. Semigroup (UniqueMap unique a)
forall unique a. UniqueMap unique a
forall unique a. [UniqueMap unique a] -> UniqueMap unique a
forall unique a.
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
mconcat :: [UniqueMap unique a] -> UniqueMap unique a
$cmconcat :: forall unique a. [UniqueMap unique a] -> UniqueMap unique a
mappend :: UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
$cmappend :: forall unique a.
UniqueMap unique a -> UniqueMap unique a -> UniqueMap unique a
mempty :: UniqueMap unique a
$cmempty :: forall unique a. UniqueMap unique a
$cp1Monoid :: forall unique a. Semigroup (UniqueMap unique a)
Monoid, a -> UniqueMap unique b -> UniqueMap unique a
(a -> b) -> UniqueMap unique a -> UniqueMap unique b
(forall a b. (a -> b) -> UniqueMap unique a -> UniqueMap unique b)
-> (forall a b. a -> UniqueMap unique b -> UniqueMap unique a)
-> Functor (UniqueMap unique)
forall a b. a -> UniqueMap unique b -> UniqueMap unique a
forall a b. (a -> b) -> UniqueMap unique a -> UniqueMap unique b
forall unique a b. a -> UniqueMap unique b -> UniqueMap unique a
forall unique a b.
(a -> b) -> UniqueMap unique a -> UniqueMap unique b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> UniqueMap unique b -> UniqueMap unique a
$c<$ :: forall unique a b. a -> UniqueMap unique b -> UniqueMap unique a
fmap :: (a -> b) -> UniqueMap unique a -> UniqueMap unique b
$cfmap :: forall unique a b.
(a -> b) -> UniqueMap unique a -> UniqueMap unique b
Functor)

-- | Insert a value by a unique.
insertByUnique :: Coercible unique Unique => unique -> a -> UniqueMap unique a -> UniqueMap unique a
insertByUnique :: unique -> a -> UniqueMap unique a -> UniqueMap unique a
insertByUnique unique
uniq = (IntMap a -> IntMap a) -> UniqueMap unique a -> UniqueMap unique a
coerce ((IntMap a -> IntMap a)
 -> UniqueMap unique a -> UniqueMap unique a)
-> (a -> IntMap a -> IntMap a)
-> a
-> UniqueMap unique a
-> UniqueMap unique a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> a -> IntMap a -> IntMap a
forall a. Int -> a -> IntMap a -> IntMap a
IM.insert (unique -> Int
coerce unique
uniq)

-- | Insert a value by the unique of a name.
insertByName :: HasUnique name unique => name -> a -> UniqueMap unique a -> UniqueMap unique a
insertByName :: name -> a -> UniqueMap unique a -> UniqueMap unique a
insertByName = unique -> a -> UniqueMap unique a -> UniqueMap unique a
forall unique a.
Coercible unique Unique =>
unique -> a -> UniqueMap unique a -> UniqueMap unique a
insertByUnique (unique -> a -> UniqueMap unique a -> UniqueMap unique a)
-> (name -> unique)
-> name
-> a
-> UniqueMap unique a
-> UniqueMap unique a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting unique name unique -> name -> unique
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting unique name unique
forall a unique. HasUnique a unique => Lens' a unique
unique

-- | Insert a value by the index of the unique of a name.
-- Unlike 'insertByUnique' and 'insertByName', this function does not provide any static guarantees,
-- so you can for example insert by a type-level name in a map from term-level uniques.
insertByNameIndex
    :: (HasUnique name unique1, Coercible unique2 Unique)
    => name -> a -> UniqueMap unique2 a -> UniqueMap unique2 a
insertByNameIndex :: name -> a -> UniqueMap unique2 a -> UniqueMap unique2 a
insertByNameIndex = unique2 -> a -> UniqueMap unique2 a -> UniqueMap unique2 a
forall unique a.
Coercible unique Unique =>
unique -> a -> UniqueMap unique a -> UniqueMap unique a
insertByUnique (unique2 -> a -> UniqueMap unique2 a -> UniqueMap unique2 a)
-> (name -> unique2)
-> name
-> a
-> UniqueMap unique2 a
-> UniqueMap unique2 a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. unique1 -> unique2
coerce (unique1 -> unique2) -> (name -> unique1) -> name -> unique2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting unique1 name unique1 -> name -> unique1
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting unique1 name unique1
forall a unique. HasUnique a unique => Lens' a unique
unique

-- | Convert a 'Foldable' into a 'UniqueMap' using the given insertion function.
fromFoldable
    :: Foldable f
    => (i -> a -> UniqueMap unique a -> UniqueMap unique a) -> f (i, a) -> UniqueMap unique a
fromFoldable :: (i -> a -> UniqueMap unique a -> UniqueMap unique a)
-> f (i, a) -> UniqueMap unique a
fromFoldable i -> a -> UniqueMap unique a -> UniqueMap unique a
ins = (UniqueMap unique a -> (i, a) -> UniqueMap unique a)
-> UniqueMap unique a -> f (i, a) -> UniqueMap unique a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (((i, a) -> UniqueMap unique a -> UniqueMap unique a)
-> UniqueMap unique a -> (i, a) -> UniqueMap unique a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (((i, a) -> UniqueMap unique a -> UniqueMap unique a)
 -> UniqueMap unique a -> (i, a) -> UniqueMap unique a)
-> ((i, a) -> UniqueMap unique a -> UniqueMap unique a)
-> UniqueMap unique a
-> (i, a)
-> UniqueMap unique a
forall a b. (a -> b) -> a -> b
$ (i -> a -> UniqueMap unique a -> UniqueMap unique a)
-> (i, a) -> UniqueMap unique a -> UniqueMap unique a
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry i -> a -> UniqueMap unique a -> UniqueMap unique a
ins) UniqueMap unique a
forall a. Monoid a => a
mempty

-- | Convert a 'Foldable' with uniques into a 'UniqueMap'.
fromUniques :: Foldable f => Coercible Unique unique => f (unique, a) -> UniqueMap unique a
fromUniques :: f (unique, a) -> UniqueMap unique a
fromUniques = (unique -> a -> UniqueMap unique a -> UniqueMap unique a)
-> f (unique, a) -> UniqueMap unique a
forall (f :: * -> *) i a unique.
Foldable f =>
(i -> a -> UniqueMap unique a -> UniqueMap unique a)
-> f (i, a) -> UniqueMap unique a
fromFoldable unique -> a -> UniqueMap unique a -> UniqueMap unique a
forall unique a.
Coercible unique Unique =>
unique -> a -> UniqueMap unique a -> UniqueMap unique a
insertByUnique

-- | Convert a 'Foldable' with names into a 'UniqueMap'.
fromNames :: Foldable f => HasUnique name unique => f (name, a) -> UniqueMap unique a
fromNames :: f (name, a) -> UniqueMap unique a
fromNames = (name -> a -> UniqueMap unique a -> UniqueMap unique a)
-> f (name, a) -> UniqueMap unique a
forall (f :: * -> *) i a unique.
Foldable f =>
(i -> a -> UniqueMap unique a -> UniqueMap unique a)
-> f (i, a) -> UniqueMap unique a
fromFoldable name -> a -> UniqueMap unique a -> UniqueMap unique a
forall name unique a.
HasUnique name unique =>
name -> a -> UniqueMap unique a -> UniqueMap unique a
insertByName

-- | Look up a value by a unique.
lookupUnique :: Coercible unique Unique => unique -> UniqueMap unique a -> Maybe a
lookupUnique :: unique -> UniqueMap unique a -> Maybe a
lookupUnique unique
uniq = Int -> IntMap a -> Maybe a
forall a. Int -> IntMap a -> Maybe a
IM.lookup (unique -> Int
coerce unique
uniq) (IntMap a -> Maybe a)
-> (UniqueMap unique a -> IntMap a)
-> UniqueMap unique a
-> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UniqueMap unique a -> IntMap a
forall unique a. UniqueMap unique a -> IntMap a
unUniqueMap

-- | Look up a value by the unique of a name.
lookupName :: HasUnique name unique => name -> UniqueMap unique a -> Maybe a
lookupName :: name -> UniqueMap unique a -> Maybe a
lookupName = unique -> UniqueMap unique a -> Maybe a
forall unique a.
Coercible unique Unique =>
unique -> UniqueMap unique a -> Maybe a
lookupUnique (unique -> UniqueMap unique a -> Maybe a)
-> (name -> unique) -> name -> UniqueMap unique a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting unique name unique -> name -> unique
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting unique name unique
forall a unique. HasUnique a unique => Lens' a unique
unique

-- | Look up a value by the index of the unique of a name.
-- Unlike 'lookupUnique' and 'lookupName', this function does not provide any static guarantees,
-- so you can for example look up a type-level name in a map from term-level uniques.
lookupNameIndex
    :: (HasUnique name unique1, Coercible unique2 Unique)
    => name -> UniqueMap unique2 a -> Maybe a
lookupNameIndex :: name -> UniqueMap unique2 a -> Maybe a
lookupNameIndex = unique2 -> UniqueMap unique2 a -> Maybe a
forall unique a.
Coercible unique Unique =>
unique -> UniqueMap unique a -> Maybe a
lookupUnique (unique2 -> UniqueMap unique2 a -> Maybe a)
-> (name -> unique2) -> name -> UniqueMap unique2 a -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. unique1 -> unique2
coerce (unique1 -> unique2) -> (name -> unique1) -> name -> unique2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting unique1 name unique1 -> name -> unique1
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting unique1 name unique1
forall a unique. HasUnique a unique => Lens' a unique
unique

{-# INLINE isEmpty #-}
isEmpty :: UniqueMap unique a -> Bool
isEmpty :: UniqueMap unique a -> Bool
isEmpty (UniqueMap IntMap a
m) = IntMap a -> Bool
forall a. IntMap a -> Bool
IM.null IntMap a
m