-- | The constructor reference type.
module Unison.ConstructorReference
  ( GConstructorReference (..),
    ConstructorReference,
    ConstructorReferenceId,
    reference_,
    toId,
    toShortHash,
  )
where

import Control.Lens
import Unison.DataDeclaration.ConstructorId (ConstructorId)
import Unison.Reference (TypeReference, TypeReferenceId)
import Unison.Reference qualified as Reference
import Unison.ShortHash (ShortHash)
import Unison.ShortHash qualified as ShortHash

-- | A reference to a constructor is represented by a reference to its type declaration, plus the ordinal constructor id.
data GConstructorReference r
  = ConstructorReference !r !ConstructorId
  deriving stock (GConstructorReference r -> GConstructorReference r -> Bool
(GConstructorReference r -> GConstructorReference r -> Bool)
-> (GConstructorReference r -> GConstructorReference r -> Bool)
-> Eq (GConstructorReference r)
forall r.
Eq r =>
GConstructorReference r -> GConstructorReference r -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall r.
Eq r =>
GConstructorReference r -> GConstructorReference r -> Bool
== :: GConstructorReference r -> GConstructorReference r -> Bool
$c/= :: forall r.
Eq r =>
GConstructorReference r -> GConstructorReference r -> Bool
/= :: GConstructorReference r -> GConstructorReference r -> Bool
Eq, (forall a b.
 (a -> b) -> GConstructorReference a -> GConstructorReference b)
-> (forall a b.
    a -> GConstructorReference b -> GConstructorReference a)
-> Functor GConstructorReference
forall a b. a -> GConstructorReference b -> GConstructorReference a
forall a b.
(a -> b) -> GConstructorReference a -> GConstructorReference 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) -> GConstructorReference a -> GConstructorReference b
fmap :: forall a b.
(a -> b) -> GConstructorReference a -> GConstructorReference b
$c<$ :: forall a b. a -> GConstructorReference b -> GConstructorReference a
<$ :: forall a b. a -> GConstructorReference b -> GConstructorReference a
Functor, Eq (GConstructorReference r)
Eq (GConstructorReference r) =>
(GConstructorReference r -> GConstructorReference r -> Ordering)
-> (GConstructorReference r -> GConstructorReference r -> Bool)
-> (GConstructorReference r -> GConstructorReference r -> Bool)
-> (GConstructorReference r -> GConstructorReference r -> Bool)
-> (GConstructorReference r -> GConstructorReference r -> Bool)
-> (GConstructorReference r
    -> GConstructorReference r -> GConstructorReference r)
-> (GConstructorReference r
    -> GConstructorReference r -> GConstructorReference r)
-> Ord (GConstructorReference r)
GConstructorReference r -> GConstructorReference r -> Bool
GConstructorReference r -> GConstructorReference r -> Ordering
GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
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 r. Ord r => Eq (GConstructorReference r)
forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Bool
forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Ordering
forall r.
Ord r =>
GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
$ccompare :: forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Ordering
compare :: GConstructorReference r -> GConstructorReference r -> Ordering
$c< :: forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Bool
< :: GConstructorReference r -> GConstructorReference r -> Bool
$c<= :: forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Bool
<= :: GConstructorReference r -> GConstructorReference r -> Bool
$c> :: forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Bool
> :: GConstructorReference r -> GConstructorReference r -> Bool
$c>= :: forall r.
Ord r =>
GConstructorReference r -> GConstructorReference r -> Bool
>= :: GConstructorReference r -> GConstructorReference r -> Bool
$cmax :: forall r.
Ord r =>
GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
max :: GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
$cmin :: forall r.
Ord r =>
GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
min :: GConstructorReference r
-> GConstructorReference r -> GConstructorReference r
Ord, Int -> GConstructorReference r -> ShowS
[GConstructorReference r] -> ShowS
GConstructorReference r -> String
(Int -> GConstructorReference r -> ShowS)
-> (GConstructorReference r -> String)
-> ([GConstructorReference r] -> ShowS)
-> Show (GConstructorReference r)
forall r. Show r => Int -> GConstructorReference r -> ShowS
forall r. Show r => [GConstructorReference r] -> ShowS
forall r. Show r => GConstructorReference r -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall r. Show r => Int -> GConstructorReference r -> ShowS
showsPrec :: Int -> GConstructorReference r -> ShowS
$cshow :: forall r. Show r => GConstructorReference r -> String
show :: GConstructorReference r -> String
$cshowList :: forall r. Show r => [GConstructorReference r] -> ShowS
showList :: [GConstructorReference r] -> ShowS
Show)

type ConstructorReference = GConstructorReference TypeReference

type ConstructorReferenceId = GConstructorReference TypeReferenceId

-- | A lens onto the reference part of a constructor reference.
reference_ :: Lens (GConstructorReference r) (GConstructorReference s) r s
reference_ :: forall r s (f :: * -> *).
Functor f =>
(r -> f s)
-> GConstructorReference r -> f (GConstructorReference s)
reference_ =
  (GConstructorReference r -> r)
-> (GConstructorReference r -> s -> GConstructorReference s)
-> Lens (GConstructorReference r) (GConstructorReference s) r s
forall s a b t. (s -> a) -> (s -> b -> t) -> Lens s t a b
lens (\(ConstructorReference r
r ConstructorId
_) -> r
r) \(ConstructorReference r
_ ConstructorId
i) s
r -> s -> ConstructorId -> GConstructorReference s
forall r. r -> ConstructorId -> GConstructorReference r
ConstructorReference s
r ConstructorId
i

toId :: ConstructorReference -> Maybe ConstructorReferenceId
toId :: ConstructorReference -> Maybe ConstructorReferenceId
toId (ConstructorReference TypeReference
typeRef ConstructorId
conId) =
  TypeReferenceId -> ConstructorId -> ConstructorReferenceId
forall r. r -> ConstructorId -> GConstructorReference r
ConstructorReference (TypeReferenceId -> ConstructorId -> ConstructorReferenceId)
-> Maybe TypeReferenceId
-> Maybe (ConstructorId -> ConstructorReferenceId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypeReference -> Maybe TypeReferenceId
Reference.toId TypeReference
typeRef Maybe (ConstructorId -> ConstructorReferenceId)
-> Maybe ConstructorId -> Maybe ConstructorReferenceId
forall a b. Maybe (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ConstructorId -> Maybe ConstructorId
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ConstructorId
conId

toShortHash :: ConstructorReference -> ShortHash
toShortHash :: ConstructorReference -> ShortHash
toShortHash (ConstructorReference TypeReference
r ConstructorId
i) =
  case TypeReference -> ShortHash
Reference.toShortHash TypeReference
r of
    ShortHash.Builtin Text
b -> Text -> ShortHash
ShortHash.Builtin Text
b
    ShortHash.ShortHash Text
prefix Maybe ConstructorId
cycle Maybe ConstructorId
_cid -> Text -> Maybe ConstructorId -> Maybe ConstructorId -> ShortHash
ShortHash.ShortHash Text
prefix Maybe ConstructorId
cycle (ConstructorId -> Maybe ConstructorId
forall a. a -> Maybe a
Just ConstructorId
i)