module U.Codebase.Sqlite.Patch.Diff where

import Data.Bifunctor (Bifunctor (bimap))
import Data.Map (Map)
import Data.Set (Set)
import Data.Set qualified as Set
import U.Codebase.Reference (Reference')
import U.Codebase.Referent (Referent')
import U.Codebase.Sqlite.DbId qualified as Db
import U.Codebase.Sqlite.LocalIds (LocalDefnId, LocalHashId, LocalTextId)
import U.Codebase.Sqlite.Patch.TermEdit (TermEdit')
import U.Codebase.Sqlite.Patch.TypeEdit (TypeEdit')
import Unison.Util.Map qualified as Map

type PatchDiff = PatchDiff' Db.TextId Db.HashId Db.ObjectId

type LocalPatchDiff = PatchDiff' LocalTextId LocalHashId LocalDefnId

type Referent'' t h = Referent' (Reference' t h) (Reference' t h)

-- | diff. = min. - sub.
data PatchDiff' t h d = PatchDiff
  { -- | elements present in min. but absent in sub.
    forall t h d.
PatchDiff' t h d -> Map (Referent'' t h) (Set (TermEdit' t d))
addedTermEdits :: Map (Referent'' t h) (Set (TermEdit' t d)),
    forall t h d.
PatchDiff' t h d -> Map (Reference' t h) (Set (TypeEdit' t d))
addedTypeEdits :: Map (Reference' t h) (Set (TypeEdit' t d)),
    -- | elements missing in min. but present in sub.
    forall t h d.
PatchDiff' t h d -> Map (Referent'' t h) (Set (TermEdit' t d))
removedTermEdits :: Map (Referent'' t h) (Set (TermEdit' t d)),
    forall t h d.
PatchDiff' t h d -> Map (Reference' t h) (Set (TypeEdit' t d))
removedTypeEdits :: Map (Reference' t h) (Set (TypeEdit' t d))
  }
  deriving (PatchDiff' t h d -> PatchDiff' t h d -> Bool
(PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> (PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> Eq (PatchDiff' t h d)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall t h d.
(Eq t, Eq h, Eq d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
$c== :: forall t h d.
(Eq t, Eq h, Eq d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
== :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
$c/= :: forall t h d.
(Eq t, Eq h, Eq d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
/= :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
Eq, Eq (PatchDiff' t h d)
Eq (PatchDiff' t h d) =>
(PatchDiff' t h d -> PatchDiff' t h d -> Ordering)
-> (PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> (PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> (PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> (PatchDiff' t h d -> PatchDiff' t h d -> Bool)
-> (PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d)
-> (PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d)
-> Ord (PatchDiff' t h d)
PatchDiff' t h d -> PatchDiff' t h d -> Bool
PatchDiff' t h d -> PatchDiff' t h d -> Ordering
PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
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 t h d. (Ord t, Ord h, Ord d) => Eq (PatchDiff' t h d)
forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Ordering
forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
$ccompare :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Ordering
compare :: PatchDiff' t h d -> PatchDiff' t h d -> Ordering
$c< :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
< :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
$c<= :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
<= :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
$c> :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
> :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
$c>= :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> Bool
>= :: PatchDiff' t h d -> PatchDiff' t h d -> Bool
$cmax :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
max :: PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
$cmin :: forall t h d.
(Ord t, Ord h, Ord d) =>
PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
min :: PatchDiff' t h d -> PatchDiff' t h d -> PatchDiff' t h d
Ord, Int -> PatchDiff' t h d -> ShowS
[PatchDiff' t h d] -> ShowS
PatchDiff' t h d -> String
(Int -> PatchDiff' t h d -> ShowS)
-> (PatchDiff' t h d -> String)
-> ([PatchDiff' t h d] -> ShowS)
-> Show (PatchDiff' t h d)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall t h d.
(Show t, Show h, Show d) =>
Int -> PatchDiff' t h d -> ShowS
forall t h d.
(Show t, Show h, Show d) =>
[PatchDiff' t h d] -> ShowS
forall t h d.
(Show t, Show h, Show d) =>
PatchDiff' t h d -> String
$cshowsPrec :: forall t h d.
(Show t, Show h, Show d) =>
Int -> PatchDiff' t h d -> ShowS
showsPrec :: Int -> PatchDiff' t h d -> ShowS
$cshow :: forall t h d.
(Show t, Show h, Show d) =>
PatchDiff' t h d -> String
show :: PatchDiff' t h d -> String
$cshowList :: forall t h d.
(Show t, Show h, Show d) =>
[PatchDiff' t h d] -> ShowS
showList :: [PatchDiff' t h d] -> ShowS
Show)

trimap ::
  (Ord t', Ord h', Ord d') =>
  (t -> t') ->
  (h -> h') ->
  (d -> d') ->
  PatchDiff' t h d ->
  PatchDiff' t' h' d'
trimap :: forall t' h' d' t h d.
(Ord t', Ord h', Ord d') =>
(t -> t')
-> (h -> h')
-> (d -> d')
-> PatchDiff' t h d
-> PatchDiff' t' h' d'
trimap t -> t'
ft h -> h'
fh d -> d'
fd (PatchDiff Map (Referent'' t h) (Set (TermEdit' t d))
atm Map (Reference' t h) (Set (TypeEdit' t d))
atp Map (Referent'' t h) (Set (TermEdit' t d))
rtm Map (Reference' t h) (Set (TypeEdit' t d))
rtp) =
  Map (Referent'' t' h') (Set (TermEdit' t' d'))
-> Map (Reference' t' h') (Set (TypeEdit' t' d'))
-> Map (Referent'' t' h') (Set (TermEdit' t' d'))
-> Map (Reference' t' h') (Set (TypeEdit' t' d'))
-> PatchDiff' t' h' d'
forall t h d.
Map (Referent'' t h) (Set (TermEdit' t d))
-> Map (Reference' t h) (Set (TypeEdit' t d))
-> Map (Referent'' t h) (Set (TermEdit' t d))
-> Map (Reference' t h) (Set (TypeEdit' t d))
-> PatchDiff' t h d
PatchDiff
    ((Referent'' t h -> Referent'' t' h')
-> (Set (TermEdit' t d) -> Set (TermEdit' t' d'))
-> Map (Referent'' t h) (Set (TermEdit' t d))
-> Map (Referent'' t' h') (Set (TermEdit' t' d'))
forall a' a b b'.
Ord a' =>
(a -> a') -> (b -> b') -> Map a b -> Map a' b'
Map.bimap Referent'' t h -> Referent'' t' h'
bimapReferent ((TermEdit' t d -> TermEdit' t' d')
-> Set (TermEdit' t d) -> Set (TermEdit' t' d')
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map ((t -> t') -> (d -> d') -> TermEdit' t d -> TermEdit' t' d'
forall a b c d.
(a -> b) -> (c -> d) -> TermEdit' a c -> TermEdit' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft d -> d'
fd)) Map (Referent'' t h) (Set (TermEdit' t d))
atm)
    ((Reference' t h -> Reference' t' h')
-> (Set (TypeEdit' t d) -> Set (TypeEdit' t' d'))
-> Map (Reference' t h) (Set (TypeEdit' t d))
-> Map (Reference' t' h') (Set (TypeEdit' t' d'))
forall a' a b b'.
Ord a' =>
(a -> a') -> (b -> b') -> Map a b -> Map a' b'
Map.bimap ((t -> t') -> (h -> h') -> Reference' t h -> Reference' t' h'
forall a b c d.
(a -> b) -> (c -> d) -> Reference' a c -> Reference' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft h -> h'
fh) ((TypeEdit' t d -> TypeEdit' t' d')
-> Set (TypeEdit' t d) -> Set (TypeEdit' t' d')
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map ((t -> t') -> (d -> d') -> TypeEdit' t d -> TypeEdit' t' d'
forall a b c d.
(a -> b) -> (c -> d) -> TypeEdit' a c -> TypeEdit' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft d -> d'
fd)) Map (Reference' t h) (Set (TypeEdit' t d))
atp)
    ((Referent'' t h -> Referent'' t' h')
-> (Set (TermEdit' t d) -> Set (TermEdit' t' d'))
-> Map (Referent'' t h) (Set (TermEdit' t d))
-> Map (Referent'' t' h') (Set (TermEdit' t' d'))
forall a' a b b'.
Ord a' =>
(a -> a') -> (b -> b') -> Map a b -> Map a' b'
Map.bimap Referent'' t h -> Referent'' t' h'
bimapReferent ((TermEdit' t d -> TermEdit' t' d')
-> Set (TermEdit' t d) -> Set (TermEdit' t' d')
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map ((t -> t') -> (d -> d') -> TermEdit' t d -> TermEdit' t' d'
forall a b c d.
(a -> b) -> (c -> d) -> TermEdit' a c -> TermEdit' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft d -> d'
fd)) Map (Referent'' t h) (Set (TermEdit' t d))
rtm)
    ((Reference' t h -> Reference' t' h')
-> (Set (TypeEdit' t d) -> Set (TypeEdit' t' d'))
-> Map (Reference' t h) (Set (TypeEdit' t d))
-> Map (Reference' t' h') (Set (TypeEdit' t' d'))
forall a' a b b'.
Ord a' =>
(a -> a') -> (b -> b') -> Map a b -> Map a' b'
Map.bimap ((t -> t') -> (h -> h') -> Reference' t h -> Reference' t' h'
forall a b c d.
(a -> b) -> (c -> d) -> Reference' a c -> Reference' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft h -> h'
fh) ((TypeEdit' t d -> TypeEdit' t' d')
-> Set (TypeEdit' t d) -> Set (TypeEdit' t' d')
forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map ((t -> t') -> (d -> d') -> TypeEdit' t d -> TypeEdit' t' d'
forall a b c d.
(a -> b) -> (c -> d) -> TypeEdit' a c -> TypeEdit' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft d -> d'
fd)) Map (Reference' t h) (Set (TypeEdit' t d))
rtp)
  where
    bimapReferent :: Referent'' t h -> Referent'' t' h'
bimapReferent = (Reference' t h -> Reference' t' h')
-> (Reference' t h -> Reference' t' h')
-> Referent'' t h
-> Referent'' t' h'
forall a b c d.
(a -> b) -> (c -> d) -> Referent' a c -> Referent' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap ((t -> t') -> (h -> h') -> Reference' t h -> Reference' t' h'
forall a b c d.
(a -> b) -> (c -> d) -> Reference' a c -> Reference' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft h -> h'
fh) ((t -> t') -> (h -> h') -> Reference' t h -> Reference' t' h'
forall a b c d.
(a -> b) -> (c -> d) -> Reference' a c -> Reference' b d
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap t -> t'
ft h -> h'
fh)