module Unison.HashQualified where

import Data.Text qualified as Text
import Unison.ConstructorReference (ConstructorReference)
import Unison.ConstructorReference qualified as ConstructorReference
import Unison.Name (Name)
import Unison.Name qualified as Name
import Unison.Prelude hiding (fromString)
import Unison.Reference (Reference)
import Unison.Reference qualified as Reference
import Unison.Referent (Referent)
import Unison.Referent qualified as Referent
import Unison.ShortHash (ShortHash)
import Unison.ShortHash qualified as SH
import Prelude hiding (take)

data HashQualified n
  = NameOnly n
  | HashOnly ShortHash
  | HashQualified n ShortHash
  deriving stock (HashQualified n -> HashQualified n -> Bool
(HashQualified n -> HashQualified n -> Bool)
-> (HashQualified n -> HashQualified n -> Bool)
-> Eq (HashQualified n)
forall n. Eq n => HashQualified n -> HashQualified n -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall n. Eq n => HashQualified n -> HashQualified n -> Bool
== :: HashQualified n -> HashQualified n -> Bool
$c/= :: forall n. Eq n => HashQualified n -> HashQualified n -> Bool
/= :: HashQualified n -> HashQualified n -> Bool
Eq, (forall m. Monoid m => HashQualified m -> m)
-> (forall m a. Monoid m => (a -> m) -> HashQualified a -> m)
-> (forall m a. Monoid m => (a -> m) -> HashQualified a -> m)
-> (forall a b. (a -> b -> b) -> b -> HashQualified a -> b)
-> (forall a b. (a -> b -> b) -> b -> HashQualified a -> b)
-> (forall b a. (b -> a -> b) -> b -> HashQualified a -> b)
-> (forall b a. (b -> a -> b) -> b -> HashQualified a -> b)
-> (forall a. (a -> a -> a) -> HashQualified a -> a)
-> (forall a. (a -> a -> a) -> HashQualified a -> a)
-> (forall a. HashQualified a -> [a])
-> (forall a. HashQualified a -> Bool)
-> (forall a. HashQualified a -> Int)
-> (forall a. Eq a => a -> HashQualified a -> Bool)
-> (forall a. Ord a => HashQualified a -> a)
-> (forall a. Ord a => HashQualified a -> a)
-> (forall a. Num a => HashQualified a -> a)
-> (forall a. Num a => HashQualified a -> a)
-> Foldable HashQualified
forall a. Eq a => a -> HashQualified a -> Bool
forall a. Num a => HashQualified a -> a
forall a. Ord a => HashQualified a -> a
forall m. Monoid m => HashQualified m -> m
forall a. HashQualified a -> Bool
forall a. HashQualified a -> Int
forall a. HashQualified a -> [a]
forall a. (a -> a -> a) -> HashQualified a -> a
forall m a. Monoid m => (a -> m) -> HashQualified a -> m
forall b a. (b -> a -> b) -> b -> HashQualified a -> b
forall a b. (a -> b -> b) -> b -> HashQualified a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
$cfold :: forall m. Monoid m => HashQualified m -> m
fold :: forall m. Monoid m => HashQualified m -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> HashQualified a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> HashQualified a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> HashQualified a -> m
foldMap' :: forall m a. Monoid m => (a -> m) -> HashQualified a -> m
$cfoldr :: forall a b. (a -> b -> b) -> b -> HashQualified a -> b
foldr :: forall a b. (a -> b -> b) -> b -> HashQualified a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> HashQualified a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> HashQualified a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> HashQualified a -> b
foldl :: forall b a. (b -> a -> b) -> b -> HashQualified a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> HashQualified a -> b
foldl' :: forall b a. (b -> a -> b) -> b -> HashQualified a -> b
$cfoldr1 :: forall a. (a -> a -> a) -> HashQualified a -> a
foldr1 :: forall a. (a -> a -> a) -> HashQualified a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> HashQualified a -> a
foldl1 :: forall a. (a -> a -> a) -> HashQualified a -> a
$ctoList :: forall a. HashQualified a -> [a]
toList :: forall a. HashQualified a -> [a]
$cnull :: forall a. HashQualified a -> Bool
null :: forall a. HashQualified a -> Bool
$clength :: forall a. HashQualified a -> Int
length :: forall a. HashQualified a -> Int
$celem :: forall a. Eq a => a -> HashQualified a -> Bool
elem :: forall a. Eq a => a -> HashQualified a -> Bool
$cmaximum :: forall a. Ord a => HashQualified a -> a
maximum :: forall a. Ord a => HashQualified a -> a
$cminimum :: forall a. Ord a => HashQualified a -> a
minimum :: forall a. Ord a => HashQualified a -> a
$csum :: forall a. Num a => HashQualified a -> a
sum :: forall a. Num a => HashQualified a -> a
$cproduct :: forall a. Num a => HashQualified a -> a
product :: forall a. Num a => HashQualified a -> a
Foldable, Eq (HashQualified n)
Eq (HashQualified n) =>
(HashQualified n -> HashQualified n -> Ordering)
-> (HashQualified n -> HashQualified n -> Bool)
-> (HashQualified n -> HashQualified n -> Bool)
-> (HashQualified n -> HashQualified n -> Bool)
-> (HashQualified n -> HashQualified n -> Bool)
-> (HashQualified n -> HashQualified n -> HashQualified n)
-> (HashQualified n -> HashQualified n -> HashQualified n)
-> Ord (HashQualified n)
HashQualified n -> HashQualified n -> Bool
HashQualified n -> HashQualified n -> Ordering
HashQualified n -> HashQualified n -> HashQualified n
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
forall n. Ord n => Eq (HashQualified n)
forall n. Ord n => HashQualified n -> HashQualified n -> Bool
forall n. Ord n => HashQualified n -> HashQualified n -> Ordering
forall n.
Ord n =>
HashQualified n -> HashQualified n -> HashQualified n
$ccompare :: forall n. Ord n => HashQualified n -> HashQualified n -> Ordering
compare :: HashQualified n -> HashQualified n -> Ordering
$c< :: forall n. Ord n => HashQualified n -> HashQualified n -> Bool
< :: HashQualified n -> HashQualified n -> Bool
$c<= :: forall n. Ord n => HashQualified n -> HashQualified n -> Bool
<= :: HashQualified n -> HashQualified n -> Bool
$c> :: forall n. Ord n => HashQualified n -> HashQualified n -> Bool
> :: HashQualified n -> HashQualified n -> Bool
$c>= :: forall n. Ord n => HashQualified n -> HashQualified n -> Bool
>= :: HashQualified n -> HashQualified n -> Bool
$cmax :: forall n.
Ord n =>
HashQualified n -> HashQualified n -> HashQualified n
max :: HashQualified n -> HashQualified n -> HashQualified n
$cmin :: forall n.
Ord n =>
HashQualified n -> HashQualified n -> HashQualified n
min :: HashQualified n -> HashQualified n -> HashQualified n
Ord, Functor HashQualified
Foldable HashQualified
(Functor HashQualified, Foldable HashQualified) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> HashQualified a -> f (HashQualified b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    HashQualified (f a) -> f (HashQualified a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> HashQualified a -> m (HashQualified b))
-> (forall (m :: * -> *) a.
    Monad m =>
    HashQualified (m a) -> m (HashQualified a))
-> Traversable HashQualified
forall (t :: * -> *).
(Functor t, Foldable t) =>
(forall (f :: * -> *) a b.
 Applicative f =>
 (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
HashQualified (m a) -> m (HashQualified a)
forall (f :: * -> *) a.
Applicative f =>
HashQualified (f a) -> f (HashQualified a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> HashQualified a -> m (HashQualified b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> HashQualified a -> f (HashQualified b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> HashQualified a -> f (HashQualified b)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> HashQualified a -> f (HashQualified b)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
HashQualified (f a) -> f (HashQualified a)
sequenceA :: forall (f :: * -> *) a.
Applicative f =>
HashQualified (f a) -> f (HashQualified a)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> HashQualified a -> m (HashQualified b)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> HashQualified a -> m (HashQualified b)
$csequence :: forall (m :: * -> *) a.
Monad m =>
HashQualified (m a) -> m (HashQualified a)
sequence :: forall (m :: * -> *) a.
Monad m =>
HashQualified (m a) -> m (HashQualified a)
Traversable, (forall a b. (a -> b) -> HashQualified a -> HashQualified b)
-> (forall a b. a -> HashQualified b -> HashQualified a)
-> Functor HashQualified
forall a b. a -> HashQualified b -> HashQualified a
forall a b. (a -> b) -> HashQualified a -> HashQualified b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> HashQualified a -> HashQualified b
fmap :: forall a b. (a -> b) -> HashQualified a -> HashQualified b
$c<$ :: forall a b. a -> HashQualified b -> HashQualified a
<$ :: forall a b. a -> HashQualified b -> HashQualified a
Functor, Int -> HashQualified n -> ShowS
[HashQualified n] -> ShowS
HashQualified n -> String
(Int -> HashQualified n -> ShowS)
-> (HashQualified n -> String)
-> ([HashQualified n] -> ShowS)
-> Show (HashQualified n)
forall n. Show n => Int -> HashQualified n -> ShowS
forall n. Show n => [HashQualified n] -> ShowS
forall n. Show n => HashQualified n -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall n. Show n => Int -> HashQualified n -> ShowS
showsPrec :: Int -> HashQualified n -> ShowS
$cshow :: forall n. Show n => HashQualified n -> String
show :: HashQualified n -> String
$cshowList :: forall n. Show n => [HashQualified n] -> ShowS
showList :: [HashQualified n] -> ShowS
Show, (forall x. HashQualified n -> Rep (HashQualified n) x)
-> (forall x. Rep (HashQualified n) x -> HashQualified n)
-> Generic (HashQualified n)
forall x. Rep (HashQualified n) x -> HashQualified n
forall x. HashQualified n -> Rep (HashQualified n) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall n x. Rep (HashQualified n) x -> HashQualified n
forall n x. HashQualified n -> Rep (HashQualified n) x
$cfrom :: forall n x. HashQualified n -> Rep (HashQualified n) x
from :: forall x. HashQualified n -> Rep (HashQualified n) x
$cto :: forall n x. Rep (HashQualified n) x -> HashQualified n
to :: forall x. Rep (HashQualified n) x -> HashQualified n
Generic)

stripNamespace :: Name -> HashQualified Name -> HashQualified Name
stripNamespace :: Name -> HashQualified Name -> HashQualified Name
stripNamespace Name
namespace HashQualified Name
hq = case HashQualified Name
hq of
  NameOnly Name
name -> Name -> HashQualified Name
forall n. n -> HashQualified n
NameOnly (Name -> HashQualified Name) -> Name -> HashQualified Name
forall a b. (a -> b) -> a -> b
$ Name -> Name
strip Name
name
  HashQualified Name
name ShortHash
sh -> Name -> ShortHash -> HashQualified Name
forall n. n -> ShortHash -> HashQualified n
HashQualified (Name -> Name
strip Name
name) ShortHash
sh
  HashQualified Name
ho -> HashQualified Name
ho
  where
    strip :: Name -> Name
strip Name
name =
      Name -> Maybe Name -> Name
forall a. a -> Maybe a -> a
fromMaybe Name
name (Maybe Name -> Name) -> Maybe Name -> Name
forall a b. (a -> b) -> a -> b
$ Name -> Name -> Maybe Name
Name.stripNamePrefix Name
namespace Name
name

toName :: HashQualified n -> Maybe n
toName :: forall n. HashQualified n -> Maybe n
toName = \case
  NameOnly n
name -> n -> Maybe n
forall a. a -> Maybe a
Just n
name
  HashQualified n
name ShortHash
_ -> n -> Maybe n
forall a. a -> Maybe a
Just n
name
  HashOnly ShortHash
_ -> Maybe n
forall a. Maybe a
Nothing

-- Sort the list of names by length of segments: smaller number of
-- segments is listed first. NameOnly < Hash qualified < Hash only
--
-- Examples:
--   [foo.bar.baz, bar.baz] -> [bar.baz, foo.bar.baz]
--   [#a29dj2k91, foo.bar.baz] -> [foo.bar.baz, #a29dj2k91]
--   [foo.bar#abc, foo.bar] -> [foo.bar, foo.bar#abc]
--   [.foo.bar, foo.bar] -> [foo.bar, .foo.bar]
sortByLength :: [HashQualified Name] -> [HashQualified Name]
sortByLength :: [HashQualified Name] -> [HashQualified Name]
sortByLength [HashQualified Name]
hs = (HashQualified Name -> (Int, Int))
-> [HashQualified Name] -> [HashQualified Name]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn HashQualified Name -> (Int, Int)
f [HashQualified Name]
hs
  where
    f :: HashQualified Name -> (Int, Int)
    f :: HashQualified Name -> (Int, Int)
f (NameOnly Name
n) = (NonEmpty NameSegment -> Int
forall a. NonEmpty a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Name -> NonEmpty NameSegment
Name.reverseSegments Name
n), Int
0)
    f (HashQualified Name
n ShortHash
_h) = (NonEmpty NameSegment -> Int
forall a. NonEmpty a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Name -> NonEmpty NameSegment
Name.reverseSegments Name
n), Int
1)
    f (HashOnly ShortHash
_h) = (Int
forall a. Bounded a => a
maxBound, Int
0)

hasName, hasHash :: HashQualified Name -> Bool
hasName :: HashQualified Name -> Bool
hasName = Maybe Name -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Name -> Bool)
-> (HashQualified Name -> Maybe Name) -> HashQualified Name -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashQualified Name -> Maybe Name
forall n. HashQualified n -> Maybe n
toName
hasHash :: HashQualified Name -> Bool
hasHash = Maybe ShortHash -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ShortHash -> Bool)
-> (HashQualified Name -> Maybe ShortHash)
-> HashQualified Name
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashQualified Name -> Maybe ShortHash
forall n. HashQualified n -> Maybe ShortHash
toHash

toHash :: HashQualified n -> Maybe ShortHash
toHash :: forall n. HashQualified n -> Maybe ShortHash
toHash = \case
  NameOnly n
_ -> Maybe ShortHash
forall a. Maybe a
Nothing
  HashQualified n
_ ShortHash
sh -> ShortHash -> Maybe ShortHash
forall a. a -> Maybe a
Just ShortHash
sh
  HashOnly ShortHash
sh -> ShortHash -> Maybe ShortHash
forall a. a -> Maybe a
Just ShortHash
sh

-- partial: assumes either a name or hash is provided (or both)
fromNameHash :: Maybe Name -> Maybe ShortHash -> HashQualified Name
fromNameHash :: Maybe Name -> Maybe ShortHash -> HashQualified Name
fromNameHash Maybe Name
n Maybe ShortHash
h = case Maybe Name
n of
  Just Name
name -> case Maybe ShortHash
h of
    Just ShortHash
hash -> Name -> ShortHash -> HashQualified Name
forall n. n -> ShortHash -> HashQualified n
HashQualified Name
name ShortHash
hash
    Maybe ShortHash
Nothing -> Name -> HashQualified Name
forall n. n -> HashQualified n
NameOnly Name
name
  Maybe Name
Nothing -> case Maybe ShortHash
h of
    Just ShortHash
hash -> ShortHash -> HashQualified Name
forall n. ShortHash -> HashQualified n
HashOnly ShortHash
hash
    Maybe ShortHash
Nothing -> String -> HashQualified Name
forall a. HasCallStack => String -> a
error String
"bad HQ construction"

take :: Int -> HashQualified n -> HashQualified n
take :: forall n. Int -> HashQualified n -> HashQualified n
take Int
i = \case
  n :: HashQualified n
n@(NameOnly n
_) -> HashQualified n
n
  HashOnly ShortHash
s -> ShortHash -> HashQualified n
forall n. ShortHash -> HashQualified n
HashOnly (Int -> ShortHash -> ShortHash
SH.shortenTo Int
i ShortHash
s)
  HashQualified n
n ShortHash
s -> if Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then n -> HashQualified n
forall n. n -> HashQualified n
NameOnly n
n else n -> ShortHash -> HashQualified n
forall n. n -> ShortHash -> HashQualified n
HashQualified n
n (Int -> ShortHash -> ShortHash
SH.shortenTo Int
i ShortHash
s)

toStringWith :: (n -> String) -> HashQualified n -> String
toStringWith :: forall n. (n -> String) -> HashQualified n -> String
toStringWith n -> String
f = Text -> String
Text.unpack (Text -> String)
-> (HashQualified n -> Text) -> HashQualified n -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (n -> Text) -> HashQualified n -> Text
forall n. (n -> Text) -> HashQualified n -> Text
toTextWith (String -> Text
Text.pack (String -> Text) -> (n -> String) -> n -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. n -> String
f)

toTextWith :: (n -> Text) -> HashQualified n -> Text
toTextWith :: forall n. (n -> Text) -> HashQualified n -> Text
toTextWith n -> Text
f = \case
  NameOnly n
name -> n -> Text
f n
name
  HashQualified n
name ShortHash
hash -> n -> Text
f n
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ShortHash -> Text
SH.toText ShortHash
hash
  HashOnly ShortHash
hash -> ShortHash -> Text
SH.toText ShortHash
hash

-- Returns the full referent in the hash.  Use HQ.take to just get a prefix
fromNamedReferent :: n -> Referent -> HashQualified n
fromNamedReferent :: forall n. n -> Referent -> HashQualified n
fromNamedReferent n
n Referent
r = n -> ShortHash -> HashQualified n
forall n. n -> ShortHash -> HashQualified n
HashQualified n
n (Referent -> ShortHash
Referent.toShortHash Referent
r)

-- Returns the full reference in the hash.  Use HQ.take to just get a prefix
fromNamedReference :: n -> Reference -> HashQualified n
fromNamedReference :: forall n. n -> Reference -> HashQualified n
fromNamedReference n
n Reference
r = n -> ShortHash -> HashQualified n
forall n. n -> ShortHash -> HashQualified n
HashQualified n
n (Reference -> ShortHash
Reference.toShortHash Reference
r)

fromReferent :: Referent -> HashQualified Name
fromReferent :: Referent -> HashQualified Name
fromReferent = ShortHash -> HashQualified Name
forall n. ShortHash -> HashQualified n
HashOnly (ShortHash -> HashQualified Name)
-> (Referent -> ShortHash) -> Referent -> HashQualified Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Referent -> ShortHash
Referent.toShortHash

fromReference :: Reference -> HashQualified Name
fromReference :: Reference -> HashQualified Name
fromReference = ShortHash -> HashQualified Name
forall n. ShortHash -> HashQualified n
HashOnly (ShortHash -> HashQualified Name)
-> (Reference -> ShortHash) -> Reference -> HashQualified Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reference -> ShortHash
Reference.toShortHash

fromPattern :: ConstructorReference -> HashQualified Name
fromPattern :: ConstructorReference -> HashQualified Name
fromPattern ConstructorReference
r = ShortHash -> HashQualified Name
forall n. ShortHash -> HashQualified n
HashOnly (ShortHash -> HashQualified Name)
-> ShortHash -> HashQualified Name
forall a b. (a -> b) -> a -> b
$ ConstructorReference -> ShortHash
ConstructorReference.toShortHash ConstructorReference
r

fromName :: n -> HashQualified n
fromName :: forall n. n -> HashQualified n
fromName = n -> HashQualified n
forall n. n -> HashQualified n
NameOnly

-- todo: find this logic elsewhere and replace with call to this
matchesNamedReferent :: Name -> Referent -> HashQualified Name -> Bool
matchesNamedReferent :: Name -> Referent -> HashQualified Name -> Bool
matchesNamedReferent Name
n Referent
r = \case
  NameOnly Name
n' -> Name
n' Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
n
  HashOnly ShortHash
sh -> ShortHash
sh ShortHash -> ShortHash -> Bool
`SH.isPrefixOf` Referent -> ShortHash
Referent.toShortHash Referent
r
  HashQualified Name
n' ShortHash
sh -> Name
n' Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
n Bool -> Bool -> Bool
&& ShortHash
sh ShortHash -> ShortHash -> Bool
`SH.isPrefixOf` Referent -> ShortHash
Referent.toShortHash Referent
r

matchesNamedReference :: Name -> Reference -> HashQualified Name -> Bool
matchesNamedReference :: Name -> Reference -> HashQualified Name -> Bool
matchesNamedReference Name
n Reference
r = \case
  NameOnly Name
n' -> Name
n' Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
n
  HashOnly ShortHash
sh -> ShortHash
sh ShortHash -> ShortHash -> Bool
`SH.isPrefixOf` Reference -> ShortHash
Reference.toShortHash Reference
r
  HashQualified Name
n' ShortHash
sh -> Name
n' Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
== Name
n Bool -> Bool -> Bool
&& ShortHash
sh ShortHash -> ShortHash -> Bool
`SH.isPrefixOf` Reference -> ShortHash
Reference.toShortHash Reference
r

-- Use `requalify hq . Referent.Ref` if you want to pass in a `Reference`.
requalify :: HashQualified Name -> Referent -> HashQualified Name
requalify :: HashQualified Name -> Referent -> HashQualified Name
requalify HashQualified Name
hq Referent
r = case HashQualified Name
hq of
  NameOnly Name
n -> Name -> Referent -> HashQualified Name
forall n. n -> Referent -> HashQualified n
fromNamedReferent Name
n Referent
r
  HashQualified Name
n ShortHash
_ -> Name -> Referent -> HashQualified Name
forall n. n -> Referent -> HashQualified n
fromNamedReferent Name
n Referent
r
  HashOnly ShortHash
_ -> Referent -> HashQualified Name
fromReferent Referent
r

instance (Name.Alphabetical n) => Name.Alphabetical (HashQualified n) where
  -- Ordered alphabetically, based on the name. Hashes come last.
  compareAlphabetical :: HashQualified n -> HashQualified n -> Ordering
compareAlphabetical HashQualified n
a HashQualified n
b =
    case (HashQualified n -> Maybe n
forall n. HashQualified n -> Maybe n
toName HashQualified n
a, HashQualified n -> Maybe n
forall n. HashQualified n -> Maybe n
toName HashQualified n
b) of
      (Just n
n, Just n
n2) -> n -> n -> Ordering
forall n. Alphabetical n => n -> n -> Ordering
Name.compareAlphabetical n
n n
n2
      (Maybe n
Nothing, Just n
_) -> Ordering
GT
      (Just n
_, Maybe n
Nothing) -> Ordering
LT
      (Maybe n
Nothing, Maybe n
Nothing) -> Ordering
EQ
      Ordering -> Ordering -> Ordering
forall a. Semigroup a => a -> a -> a
<> case (HashQualified n -> Maybe ShortHash
forall n. HashQualified n -> Maybe ShortHash
toHash HashQualified n
a, HashQualified n -> Maybe ShortHash
forall n. HashQualified n -> Maybe ShortHash
toHash HashQualified n
b) of
        (Maybe ShortHash
Nothing, Maybe ShortHash
Nothing) -> Ordering
EQ
        (Maybe ShortHash
Nothing, Just ShortHash
_) -> Ordering
LT -- prefer NameOnly to HashQualified
        (Just ShortHash
_, Maybe ShortHash
Nothing) -> Ordering
GT
        (Just ShortHash
sh, Just ShortHash
sh2) -> ShortHash -> ShortHash -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ShortHash
sh ShortHash
sh2