module Unison.Merge.Mergeblob1
  ( Mergeblob1 (..),
    hydratedDefnsLabeledDependencies,
    makeMergeblob1,
  )
where

import Control.Lens
import Data.List qualified as List
import Data.Map.Strict qualified as Map
import Data.Set qualified as Set
import Unison.DataDeclaration (Decl)
import Unison.DataDeclaration qualified as DataDeclaration
import Unison.DataDeclaration.Dependencies qualified as Decl
import Unison.DeclNameLookup (DeclNameLookup)
import Unison.LabeledDependency qualified as LD
import Unison.Merge.CombineDiffs (CombinedDiffOp, combineDiffs)
import Unison.Merge.DeclCoherencyCheck (IncoherentDeclReason, checkDeclCoherency, lenientCheckDeclCoherency)
import Unison.Merge.Diff (humanizeDiffs, nameBasedNamespaceDiff)
import Unison.Merge.DiffOp (DiffOp)
import Unison.Merge.EitherWay (EitherWay (..))
import Unison.Merge.HumanDiffOp (HumanDiffOp)
import Unison.Merge.Libdeps (applyLibdepsDiff, diffLibdeps, getTwoFreshLibdepNames, mergeLibdepsDiffs)
import Unison.Merge.Mergeblob0 (Mergeblob0 (..))
import Unison.Merge.PartialDeclNameLookup (PartialDeclNameLookup)
import Unison.Merge.PartitionCombinedDiffs (partitionCombinedDiffs)
import Unison.Merge.Synhashed (Synhashed)
import Unison.Merge.ThreeWay (ThreeWay)
import Unison.Merge.ThreeWay qualified as ThreeWay
import Unison.Merge.TwoWay (TwoWay (..))
import Unison.Merge.Unconflicts (Unconflicts)
import Unison.Name (Name)
import Unison.NameSegment (NameSegment)
import Unison.Names (Names)
import Unison.Parser.Ann (Ann)
import Unison.Prelude
import Unison.PrettyPrintEnv.Names qualified as PPE
import Unison.PrettyPrintEnvDecl qualified as PPED
import Unison.PrettyPrintEnvDecl.Names qualified as PPED
import Unison.Reference (TermReference, TermReferenceId, TypeReference, TypeReferenceId)
import Unison.Reference qualified as Reference
import Unison.Referent (Referent)
import Unison.Symbol (Symbol)
import Unison.Term (Term)
import Unison.Term qualified as Term
import Unison.Type (Type)
import Unison.Type qualified as Type
import Unison.Util.BiMultimap (BiMultimap)
import Unison.Util.Defns (Defns (..), DefnsF, DefnsF2, DefnsF3)

data Mergeblob1 libdep = Mergeblob1
  { forall libdep.
Mergeblob1 libdep
-> TwoWay (DefnsF (Map Name) TermReference TermReference)
conflicts :: TwoWay (DefnsF (Map Name) TermReference TypeReference),
    forall libdep. Mergeblob1 libdep -> TwoWay DeclNameLookup
declNameLookups :: TwoWay DeclNameLookup,
    forall libdep.
Mergeblob1 libdep
-> ThreeWay
     (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
defns :: ThreeWay (Defns (BiMultimap Referent Name) (BiMultimap TypeReference Name)),
    forall libdep.
Mergeblob1 libdep
-> DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
diff :: DefnsF2 (Map Name) CombinedDiffOp Referent TypeReference,
    forall libdep.
Mergeblob1 libdep
-> TwoWay
     (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA :: TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TypeReference),
    forall libdep.
Mergeblob1 libdep
-> TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
humanDiffsFromLCA :: TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TypeReference),
    forall libdep.
Mergeblob1 libdep
-> ThreeWay
     (DefnsF
        (Map Name)
        (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
        (TermReferenceId, Decl Symbol Ann))
hydratedDefns ::
      ThreeWay
        ( DefnsF
            (Map Name)
            (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
            (TypeReferenceId, Decl Symbol Ann)
        ),
    forall libdep. Mergeblob1 libdep -> PartialDeclNameLookup
lcaDeclNameLookup :: PartialDeclNameLookup,
    forall libdep. Mergeblob1 libdep -> Map NameSegment libdep
lcaLibdeps :: Map NameSegment libdep,
    forall libdep. Mergeblob1 libdep -> Map NameSegment libdep
libdeps :: Map NameSegment libdep,
    forall libdep.
Mergeblob1 libdep -> TwoWay (Map NameSegment (DiffOp libdep))
libdepsDiffs :: TwoWay (Map NameSegment (DiffOp libdep)),
    forall libdep.
Mergeblob1 libdep -> DefnsF Unconflicts Referent TermReference
unconflicts :: DefnsF Unconflicts Referent TypeReference
  }

-- | Get a names object for all the hydrated definitions AND their direct dependencies
hydratedDefnsLabeledDependencies ::
  DefnsF
    (Map Name)
    (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
    (TypeReferenceId, Decl Symbol Ann) ->
  Set LD.LabeledDependency
hydratedDefnsLabeledDependencies :: DefnsF
  (Map Name)
  (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
  (TermReferenceId, Decl Symbol Ann)
-> Set LabeledDependency
hydratedDefnsLabeledDependencies DefnsF
  (Map Name)
  (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
  (TermReferenceId, Decl Symbol Ann)
defns =
  let termDeps :: Set LD.LabeledDependency
      termDeps :: Set LabeledDependency
termDeps =
        Getting
  (Set LabeledDependency)
  (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
  (Set LabeledDependency)
-> Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
-> Set LabeledDependency
forall a s. Getting a s a -> s -> a
foldOf
          ( ((TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
 -> Const
      (Set LabeledDependency)
      (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
-> Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
-> Const
     (Set LabeledDependency)
     (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
forall (f :: * -> *) a. Foldable f => IndexedFold Int (f a) a
IndexedFold
  Int
  (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
  (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
folded
              (((TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
  -> Const
       (Set LabeledDependency)
       (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
 -> Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
 -> Const
      (Set LabeledDependency)
      (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))))
-> ((Set LabeledDependency
     -> Const (Set LabeledDependency) (Set LabeledDependency))
    -> (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
    -> Const
         (Set LabeledDependency)
         (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
-> Getting
     (Set LabeledDependency)
     (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
     (Set LabeledDependency)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optical
  (->)
  (->)
  (Const (Set LabeledDependency))
  TermReferenceId
  TermReferenceId
  (Set LabeledDependency)
  (Set LabeledDependency)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     (Term Symbol Ann, Type Symbol Ann)
     (Term Symbol Ann, Type Symbol Ann)
     (Set LabeledDependency)
     (Set LabeledDependency)
-> (Set LabeledDependency
    -> Const (Set LabeledDependency) (Set LabeledDependency))
-> (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
-> Const
     (Set LabeledDependency)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
forall (q :: * -> * -> *) (f :: * -> *) (r :: * -> * -> *)
       (p :: * -> * -> *) s t a b s' t'.
(Representable q, Applicative (Rep q), Applicative f,
 Bitraversable r) =>
Optical p q f s t a b
-> Optical p q f s' t' a b -> Optical p q f (r s s') (r t t') a b
beside
                ((TermReferenceId -> TermReference)
-> Optic'
     (->) (Const (Set LabeledDependency)) TermReferenceId TermReference
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to TermReferenceId -> TermReference
forall h t. Id' h -> Reference' t h
Reference.DerivedId Optic'
  (->) (Const (Set LabeledDependency)) TermReferenceId TermReference
-> ((Set LabeledDependency
     -> Const (Set LabeledDependency) (Set LabeledDependency))
    -> TermReference -> Const (Set LabeledDependency) TermReference)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     TermReferenceId
     TermReferenceId
     (Set LabeledDependency)
     (Set LabeledDependency)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TermReference -> LabeledDependency)
-> Optic'
     (->)
     (Const (Set LabeledDependency))
     TermReference
     LabeledDependency
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to TermReference -> LabeledDependency
LD.TermReference Optic'
  (->)
  (Const (Set LabeledDependency))
  TermReference
  LabeledDependency
-> ((Set LabeledDependency
     -> Const (Set LabeledDependency) (Set LabeledDependency))
    -> LabeledDependency
    -> Const (Set LabeledDependency) LabeledDependency)
-> (Set LabeledDependency
    -> Const (Set LabeledDependency) (Set LabeledDependency))
-> TermReference
-> Const (Set LabeledDependency) TermReference
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (LabeledDependency -> Set LabeledDependency)
-> (Set LabeledDependency
    -> Const (Set LabeledDependency) (Set LabeledDependency))
-> LabeledDependency
-> Const (Set LabeledDependency) LabeledDependency
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to LabeledDependency -> Set LabeledDependency
forall a. a -> Set a
Set.singleton)
                (Optical
  (->)
  (->)
  (Const (Set LabeledDependency))
  (Term Symbol Ann)
  (Term Symbol Ann)
  (Set LabeledDependency)
  (Set LabeledDependency)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     (Type Symbol Ann)
     (Type Symbol Ann)
     (Set LabeledDependency)
     (Set LabeledDependency)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     (Term Symbol Ann, Type Symbol Ann)
     (Term Symbol Ann, Type Symbol Ann)
     (Set LabeledDependency)
     (Set LabeledDependency)
forall (q :: * -> * -> *) (f :: * -> *) (r :: * -> * -> *)
       (p :: * -> * -> *) s t a b s' t'.
(Representable q, Applicative (Rep q), Applicative f,
 Bitraversable r) =>
Optical p q f s t a b
-> Optical p q f s' t' a b -> Optical p q f (r s s') (r t t') a b
beside ((Term Symbol Ann -> Set LabeledDependency)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     (Term Symbol Ann)
     (Term Symbol Ann)
     (Set LabeledDependency)
     (Set LabeledDependency)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Term Symbol Ann -> Set LabeledDependency
forall v vt at ap a.
(Ord v, Ord vt) =>
Term2 vt at ap v a -> Set LabeledDependency
Term.labeledDependencies) ((Type Symbol Ann -> Set LabeledDependency)
-> Optical
     (->)
     (->)
     (Const (Set LabeledDependency))
     (Type Symbol Ann)
     (Type Symbol Ann)
     (Set LabeledDependency)
     (Set LabeledDependency)
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Type Symbol Ann -> Set LabeledDependency
forall v a. Ord v => Type v a -> Set LabeledDependency
Type.labeledDependencies))
          )
          DefnsF
  (Map Name)
  (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
  (TermReferenceId, Decl Symbol Ann)
defns.terms

      typeDeps :: Set LD.LabeledDependency
      typeDeps :: Set LabeledDependency
typeDeps =
        DefnsF
  (Map Name)
  (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
  (TermReferenceId, Decl Symbol Ann)
defns.types
          Map Name (TermReferenceId, Decl Symbol Ann)
-> (Map Name (TermReferenceId, Decl Symbol Ann)
    -> Set LabeledDependency)
-> Set LabeledDependency
forall a b. a -> (a -> b) -> b
& ((TermReferenceId, Decl Symbol Ann) -> Set LabeledDependency)
-> Map Name (TermReferenceId, Decl Symbol Ann)
-> Set LabeledDependency
forall m a. Monoid m => (a -> m) -> Map Name a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap \(TermReferenceId
typeRefId, Decl Symbol Ann
typeDecl) ->
            TermReference -> Decl Symbol Ann -> Set LabeledDependency
forall v a.
Var v =>
TermReference -> Decl v a -> Set LabeledDependency
Decl.labeledDeclDependenciesIncludingSelfAndFieldAccessors (TermReferenceId -> TermReference
forall h t. Id' h -> Reference' t h
Reference.DerivedId TermReferenceId
typeRefId) Decl Symbol Ann
typeDecl
   in Set LabeledDependency
-> Set LabeledDependency -> Set LabeledDependency
forall a. Ord a => Set a -> Set a -> Set a
Set.union Set LabeledDependency
termDeps Set LabeledDependency
typeDeps

makeMergeblob1 ::
  forall libdep.
  (Eq libdep) =>
  Mergeblob0 libdep ->
  ThreeWay Names {- Names for _at least_ every reference in 'hydratedDefnDependencies' -} ->
  ThreeWay
    ( DefnsF
        (Map Name)
        (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
        (TypeReferenceId, Decl Symbol Ann)
    ) ->
  Either (EitherWay IncoherentDeclReason) (Mergeblob1 libdep)
makeMergeblob1 :: forall libdep.
Eq libdep =>
Mergeblob0 libdep
-> ThreeWay Names
-> ThreeWay
     (DefnsF
        (Map Name)
        (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
        (TermReferenceId, Decl Symbol Ann))
-> Either (EitherWay IncoherentDeclReason) (Mergeblob1 libdep)
makeMergeblob1 Mergeblob0 libdep
blob ThreeWay Names
names3 ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns = do
  let ppeds3 :: ThreeWay PPED.PrettyPrintEnvDecl
      ppeds3 :: ThreeWay PrettyPrintEnvDecl
ppeds3 = ThreeWay Names
names3 ThreeWay Names
-> (Names -> PrettyPrintEnvDecl) -> ThreeWay PrettyPrintEnvDecl
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \Names
names -> Namer -> Suffixifier -> PrettyPrintEnvDecl
PPED.makePPED (Names -> Namer
PPE.namer Names
names) (Names -> Suffixifier
PPE.suffixifyByHash Names
names)
  -- Make one big constructor count lookup for all type decls
  let numConstructors :: Map TermReferenceId Int
numConstructors =
        Map TermReferenceId Int
forall k a. Map k a
Map.empty
          Map TermReferenceId Int
-> (Map TermReferenceId Int -> Map TermReferenceId Int)
-> Map TermReferenceId Int
forall a b. a -> (a -> b) -> b
& [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId Int -> Map TermReferenceId Int
f (Map Name (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
forall k a. Map k a -> [a]
Map.elems ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns.alice.types)
          Map TermReferenceId Int
-> (Map TermReferenceId Int -> Map TermReferenceId Int)
-> Map TermReferenceId Int
forall a b. a -> (a -> b) -> b
& [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId Int -> Map TermReferenceId Int
f (Map Name (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
forall k a. Map k a -> [a]
Map.elems ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns.bob.types)
          Map TermReferenceId Int
-> (Map TermReferenceId Int -> Map TermReferenceId Int)
-> Map TermReferenceId Int
forall a b. a -> (a -> b) -> b
& [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId Int -> Map TermReferenceId Int
f (Map Name (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
forall k a. Map k a -> [a]
Map.elems ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns.lca.types)
        where
          f :: [(TypeReferenceId, Decl Symbol Ann)] -> Map TypeReferenceId Int -> Map TypeReferenceId Int
          f :: [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId Int -> Map TermReferenceId Int
f [(TermReferenceId, Decl Symbol Ann)]
types Map TermReferenceId Int
acc =
            (Map TermReferenceId Int
 -> (TermReferenceId, Decl Symbol Ann) -> Map TermReferenceId Int)
-> Map TermReferenceId Int
-> [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId Int
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl'
              ( \Map TermReferenceId Int
acc (TermReferenceId
ref, Decl Symbol Ann
decl) ->
                  TermReferenceId
-> Int -> Map TermReferenceId Int -> Map TermReferenceId Int
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert TermReferenceId
ref (DataDeclaration Symbol Ann -> Int
forall v a. DataDeclaration v a -> Int
DataDeclaration.constructorCount (Decl Symbol Ann -> DataDeclaration Symbol Ann
forall v a. Decl v a -> DataDeclaration v a
DataDeclaration.asDataDecl Decl Symbol Ann
decl)) Map TermReferenceId Int
acc
              )
              Map TermReferenceId Int
acc
              [(TermReferenceId, Decl Symbol Ann)]
types

  -- Make Alice/Bob decl name lookups, which can fail if either have an incoherent decl
  TwoWay DeclNameLookup
declNameLookups <- do
    DeclNameLookup
alice <- HasCallStack =>
Nametree (DefnsF (Map NameSegment) Referent TermReference)
-> Map TermReferenceId Int
-> Either IncoherentDeclReason DeclNameLookup
Nametree (DefnsF (Map NameSegment) Referent TermReference)
-> Map TermReferenceId Int
-> Either IncoherentDeclReason DeclNameLookup
checkDeclCoherency Mergeblob0 libdep
blob.nametrees.alice Map TermReferenceId Int
numConstructors Either IncoherentDeclReason DeclNameLookup
-> (Either IncoherentDeclReason DeclNameLookup
    -> Either (EitherWay IncoherentDeclReason) DeclNameLookup)
-> Either (EitherWay IncoherentDeclReason) DeclNameLookup
forall a b. a -> (a -> b) -> b
& (IncoherentDeclReason -> EitherWay IncoherentDeclReason)
-> Either IncoherentDeclReason DeclNameLookup
-> Either (EitherWay IncoherentDeclReason) DeclNameLookup
forall a c b. (a -> c) -> Either a b -> Either c b
mapLeft IncoherentDeclReason -> EitherWay IncoherentDeclReason
forall a. a -> EitherWay a
Alice
    DeclNameLookup
bob <- HasCallStack =>
Nametree (DefnsF (Map NameSegment) Referent TermReference)
-> Map TermReferenceId Int
-> Either IncoherentDeclReason DeclNameLookup
Nametree (DefnsF (Map NameSegment) Referent TermReference)
-> Map TermReferenceId Int
-> Either IncoherentDeclReason DeclNameLookup
checkDeclCoherency Mergeblob0 libdep
blob.nametrees.bob Map TermReferenceId Int
numConstructors Either IncoherentDeclReason DeclNameLookup
-> (Either IncoherentDeclReason DeclNameLookup
    -> Either (EitherWay IncoherentDeclReason) DeclNameLookup)
-> Either (EitherWay IncoherentDeclReason) DeclNameLookup
forall a b. a -> (a -> b) -> b
& (IncoherentDeclReason -> EitherWay IncoherentDeclReason)
-> Either IncoherentDeclReason DeclNameLookup
-> Either (EitherWay IncoherentDeclReason) DeclNameLookup
forall a c b. (a -> c) -> Either a b -> Either c b
mapLeft IncoherentDeclReason -> EitherWay IncoherentDeclReason
forall a. a -> EitherWay a
Bob
    pure TwoWay {DeclNameLookup
alice :: DeclNameLookup
$sel:alice:TwoWay :: DeclNameLookup
alice, DeclNameLookup
bob :: DeclNameLookup
$sel:bob:TwoWay :: DeclNameLookup
bob}

  -- Make LCA decl name lookup
  let lcaDeclNameLookup :: PartialDeclNameLookup
lcaDeclNameLookup =
        Nametree (DefnsF (Map NameSegment) Referent TermReference)
-> Map TermReferenceId Int -> PartialDeclNameLookup
lenientCheckDeclCoherency Mergeblob0 libdep
blob.nametrees.lca Map TermReferenceId Int
numConstructors

  -- Diff LCA->Alice and LCA->Bob
  let (TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA, TwoWay (DefnsF2 (Map Name) Updated Referent TermReference)
propagatedUpdates) =
        HasCallStack =>
TwoWay DeclNameLookup
-> PartialDeclNameLookup
-> ThreeWay PrettyPrintEnvDecl
-> ThreeWay
     (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
-> Defns
     (Map TermReferenceId (Term Symbol Ann))
     (Map TermReferenceId (Decl Symbol Ann))
-> (TwoWay
      (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference),
    TwoWay (DefnsF2 (Map Name) Updated Referent TermReference))
TwoWay DeclNameLookup
-> PartialDeclNameLookup
-> ThreeWay PrettyPrintEnvDecl
-> ThreeWay
     (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
-> Defns
     (Map TermReferenceId (Term Symbol Ann))
     (Map TermReferenceId (Decl Symbol Ann))
-> (TwoWay
      (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference),
    TwoWay (DefnsF2 (Map Name) Updated Referent TermReference))
nameBasedNamespaceDiff
          TwoWay DeclNameLookup
declNameLookups
          PartialDeclNameLookup
lcaDeclNameLookup
          ThreeWay PrettyPrintEnvDecl
ppeds3
          Mergeblob0 libdep
blob.defns
          Defns
            { $sel:terms:Defns :: Map TermReferenceId (Term Symbol Ann)
terms =
                (DefnsF
   (Map Name)
   (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
   (TermReferenceId, Decl Symbol Ann)
 -> Map TermReferenceId (Term Symbol Ann))
-> ThreeWay
     (DefnsF
        (Map Name)
        (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
        (TermReferenceId, Decl Symbol Ann))
-> Map TermReferenceId (Term Symbol Ann)
forall m a. Monoid m => (a -> m) -> ThreeWay a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap
                  ((Map TermReferenceId (Term Symbol Ann)
 -> (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
 -> Map TermReferenceId (Term Symbol Ann))
-> Map TermReferenceId (Term Symbol Ann)
-> [(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))]
-> Map TermReferenceId (Term Symbol Ann)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (\Map TermReferenceId (Term Symbol Ann)
acc (TermReferenceId
ref, (Term Symbol Ann
term, Type Symbol Ann
_)) -> TermReferenceId
-> Term Symbol Ann
-> Map TermReferenceId (Term Symbol Ann)
-> Map TermReferenceId (Term Symbol Ann)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert TermReferenceId
ref Term Symbol Ann
term Map TermReferenceId (Term Symbol Ann)
acc) Map TermReferenceId (Term Symbol Ann)
forall k a. Map k a
Map.empty ([(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))]
 -> Map TermReferenceId (Term Symbol Ann))
-> (DefnsF
      (Map Name)
      (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
      (TermReferenceId, Decl Symbol Ann)
    -> [(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))])
-> DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann)
-> Map TermReferenceId (Term Symbol Ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
-> [(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))]
forall k a. Map k a -> [a]
Map.elems (Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
 -> [(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))])
-> (DefnsF
      (Map Name)
      (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
      (TermReferenceId, Decl Symbol Ann)
    -> Map Name (TermReferenceId, (Term Symbol Ann, Type Symbol Ann)))
-> DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, (Term Symbol Ann, Type Symbol Ann))]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.terms))
                  ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns,
              $sel:types:Defns :: Map TermReferenceId (Decl Symbol Ann)
types =
                (DefnsF
   (Map Name)
   (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
   (TermReferenceId, Decl Symbol Ann)
 -> Map TermReferenceId (Decl Symbol Ann))
-> ThreeWay
     (DefnsF
        (Map Name)
        (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
        (TermReferenceId, Decl Symbol Ann))
-> Map TermReferenceId (Decl Symbol Ann)
forall m a. Monoid m => (a -> m) -> ThreeWay a -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap
                  ((Map TermReferenceId (Decl Symbol Ann)
 -> (TermReferenceId, Decl Symbol Ann)
 -> Map TermReferenceId (Decl Symbol Ann))
-> Map TermReferenceId (Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
-> Map TermReferenceId (Decl Symbol Ann)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (\Map TermReferenceId (Decl Symbol Ann)
acc (TermReferenceId
ref, Decl Symbol Ann
typ) -> TermReferenceId
-> Decl Symbol Ann
-> Map TermReferenceId (Decl Symbol Ann)
-> Map TermReferenceId (Decl Symbol Ann)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert TermReferenceId
ref Decl Symbol Ann
typ Map TermReferenceId (Decl Symbol Ann)
acc) Map TermReferenceId (Decl Symbol Ann)
forall k a. Map k a
Map.empty ([(TermReferenceId, Decl Symbol Ann)]
 -> Map TermReferenceId (Decl Symbol Ann))
-> (DefnsF
      (Map Name)
      (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
      (TermReferenceId, Decl Symbol Ann)
    -> [(TermReferenceId, Decl Symbol Ann)])
-> DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann)
-> Map TermReferenceId (Decl Symbol Ann)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Name (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
forall k a. Map k a -> [a]
Map.elems (Map Name (TermReferenceId, Decl Symbol Ann)
 -> [(TermReferenceId, Decl Symbol Ann)])
-> (DefnsF
      (Map Name)
      (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
      (TermReferenceId, Decl Symbol Ann)
    -> Map Name (TermReferenceId, Decl Symbol Ann))
-> DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann)
-> [(TermReferenceId, Decl Symbol Ann)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.types))
                  ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns
            }

  -- Combine the LCA->Alice and LCA->Bob diffs together
  let diff :: DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
diff = TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
-> DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
combineDiffs TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA

  let humanDiffsFromLCA :: TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
humanDiffsFromLCA = ThreeWay Names
-> TwoWay
     (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
-> TwoWay (DefnsF2 (Map Name) Updated Referent TermReference)
-> TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
humanizeDiffs ThreeWay Names
names3 TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA TwoWay (DefnsF2 (Map Name) Updated Referent TermReference)
propagatedUpdates

  -- Partition the combined diff into the conflicted things and the unconflicted things
  let (TwoWay (DefnsF (Map Name) TermReference TermReference)
conflicts, DefnsF Unconflicts Referent TermReference
unconflicts) =
        TwoWay
  (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
-> TwoWay DeclNameLookup
-> DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
-> (TwoWay (DefnsF (Map Name) TermReference TermReference),
    DefnsF Unconflicts Referent TermReference)
partitionCombinedDiffs (ThreeWay
  (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
-> TwoWay
     (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
forall a. ThreeWay a -> TwoWay a
ThreeWay.forgetLca Mergeblob0 libdep
blob.defns) TwoWay DeclNameLookup
declNameLookups DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
diff

  -- Diff and merge libdeps
  let libdepsDiffs :: TwoWay (Map NameSegment (DiffOp libdep))
      libdepsDiffs :: TwoWay (Map NameSegment (DiffOp libdep))
libdepsDiffs =
        ThreeWay (Map NameSegment libdep)
-> TwoWay (Map NameSegment (DiffOp libdep))
forall k v.
(Ord k, Eq v) =>
ThreeWay (Map k v) -> TwoWay (Map k (DiffOp v))
diffLibdeps Mergeblob0 libdep
blob.libdeps

  let libdeps :: Map NameSegment libdep
      libdeps :: Map NameSegment libdep
libdeps =
        (Set NameSegment -> NameSegment -> (NameSegment, NameSegment))
-> ThreeWay (Map NameSegment libdep)
-> Map NameSegment (LibdepDiffOp libdep)
-> Map NameSegment libdep
forall k v.
Ord k =>
(Set k -> k -> (k, k))
-> ThreeWay (Map k v) -> Map k (LibdepDiffOp v) -> Map k v
applyLibdepsDiff Set NameSegment -> NameSegment -> (NameSegment, NameSegment)
getTwoFreshLibdepNames Mergeblob0 libdep
blob.libdeps (TwoWay (Map NameSegment (DiffOp libdep))
-> Map NameSegment (LibdepDiffOp libdep)
forall k v.
(Ord k, Eq v) =>
TwoWay (Map k (DiffOp v)) -> Map k (LibdepDiffOp v)
mergeLibdepsDiffs TwoWay (Map NameSegment (DiffOp libdep))
libdepsDiffs)

  pure
    Mergeblob1
      { TwoWay (DefnsF (Map Name) TermReference TermReference)
$sel:conflicts:Mergeblob1 :: TwoWay (DefnsF (Map Name) TermReference TermReference)
conflicts :: TwoWay (DefnsF (Map Name) TermReference TermReference)
conflicts,
        TwoWay DeclNameLookup
$sel:declNameLookups:Mergeblob1 :: TwoWay DeclNameLookup
declNameLookups :: TwoWay DeclNameLookup
declNameLookups,
        $sel:defns:Mergeblob1 :: ThreeWay
  (Defns (BiMultimap Referent Name) (BiMultimap TermReference Name))
defns = Mergeblob0 libdep
blob.defns,
        DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
$sel:diff:Mergeblob1 :: DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
diff :: DefnsF2 (Map Name) CombinedDiffOp Referent TermReference
diff,
        TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
$sel:diffsFromLCA:Mergeblob1 :: TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA :: TwoWay (DefnsF3 (Map Name) DiffOp Synhashed Referent TermReference)
diffsFromLCA,
        TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
$sel:humanDiffsFromLCA:Mergeblob1 :: TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
humanDiffsFromLCA :: TwoWay (DefnsF2 (Map Name) HumanDiffOp Referent TermReference)
humanDiffsFromLCA,
        ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
$sel:hydratedDefns:Mergeblob1 :: ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns :: ThreeWay
  (DefnsF
     (Map Name)
     (TermReferenceId, (Term Symbol Ann, Type Symbol Ann))
     (TermReferenceId, Decl Symbol Ann))
hydratedDefns,
        PartialDeclNameLookup
$sel:lcaDeclNameLookup:Mergeblob1 :: PartialDeclNameLookup
lcaDeclNameLookup :: PartialDeclNameLookup
lcaDeclNameLookup,
        $sel:lcaLibdeps:Mergeblob1 :: Map NameSegment libdep
lcaLibdeps = Mergeblob0 libdep
blob.libdeps.lca,
        Map NameSegment libdep
$sel:libdeps:Mergeblob1 :: Map NameSegment libdep
libdeps :: Map NameSegment libdep
libdeps,
        TwoWay (Map NameSegment (DiffOp libdep))
$sel:libdepsDiffs:Mergeblob1 :: TwoWay (Map NameSegment (DiffOp libdep))
libdepsDiffs :: TwoWay (Map NameSegment (DiffOp libdep))
libdepsDiffs,
        DefnsF Unconflicts Referent TermReference
$sel:unconflicts:Mergeblob1 :: DefnsF Unconflicts Referent TermReference
unconflicts :: DefnsF Unconflicts Referent TermReference
unconflicts
      }