module Unison.Codebase.Editor.HandleInput.Update
  ( doSlurpAdds,
  )
where

import Unison.Codebase.Branch (Branch0)
import Unison.Codebase.Branch qualified as Branch
import Unison.Codebase.BranchUtil qualified as BranchUtil
import Unison.Codebase.Editor.SlurpComponent (SlurpComponent (..))
import Unison.Codebase.Editor.SlurpComponent qualified as SC
import Unison.Codebase.Path (Path)
import Unison.Codebase.Path qualified as Path
import Unison.Names qualified as Names
import Unison.Parser.Ann (Ann (..))
import Unison.Prelude
import Unison.Symbol (Symbol)
import Unison.Syntax.Name qualified as Name (unsafeParseVar)
import Unison.UnisonFile (TypecheckedUnisonFile)
import Unison.UnisonFile qualified as UF
import Unison.UnisonFile.Names qualified as UF
import Unison.Var qualified as Var

-- updates the namespace for adding `slurp`
doSlurpAdds ::
  forall m.
  (Monad m) =>
  SlurpComponent ->
  TypecheckedUnisonFile Symbol Ann ->
  (Branch0 m -> Branch0 m)
doSlurpAdds :: forall (m :: * -> *).
Monad m =>
SlurpComponent
-> TypecheckedUnisonFile Symbol Ann -> Branch0 m -> Branch0 m
doSlurpAdds SlurpComponent
slurp TypecheckedUnisonFile Symbol Ann
uf = [(Path, Branch0 m -> Branch0 m)] -> Branch0 m -> Branch0 m
forall (f :: * -> *) (m :: * -> *).
(Monad m, Foldable f) =>
f (Path, Branch0 m -> Branch0 m) -> Branch0 m -> Branch0 m
Branch.batchUpdates ([(Path, Branch0 m -> Branch0 m)]
typeActions [(Path, Branch0 m -> Branch0 m)]
-> [(Path, Branch0 m -> Branch0 m)]
-> [(Path, Branch0 m -> Branch0 m)]
forall a. Semigroup a => a -> a -> a
<> [(Path, Branch0 m -> Branch0 m)]
termActions)
  where
    typeActions :: [(Path, Branch0 m -> Branch0 m)]
typeActions = (Symbol -> (Path, Branch0 m -> Branch0 m))
-> [Symbol] -> [(Path, Branch0 m -> Branch0 m)]
forall a b. (a -> b) -> [a] -> [b]
map Symbol -> (Path, Branch0 m -> Branch0 m)
doType ([Symbol] -> [(Path, Branch0 m -> Branch0 m)])
-> (Set Symbol -> [Symbol])
-> Set Symbol
-> [(Path, Branch0 m -> Branch0 m)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Symbol -> [Symbol]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Set Symbol -> [(Path, Branch0 m -> Branch0 m)])
-> Set Symbol -> [(Path, Branch0 m -> Branch0 m)]
forall a b. (a -> b) -> a -> b
$ SlurpComponent -> Set Symbol
SC.types SlurpComponent
slurp
    termActions :: [(Path, Branch0 m -> Branch0 m)]
termActions =
      (Symbol -> (Path, Branch0 m -> Branch0 m))
-> [Symbol] -> [(Path, Branch0 m -> Branch0 m)]
forall a b. (a -> b) -> [a] -> [b]
map Symbol -> (Path, Branch0 m -> Branch0 m)
doTerm ([Symbol] -> [(Path, Branch0 m -> Branch0 m)])
-> (Set Symbol -> [Symbol])
-> Set Symbol
-> [(Path, Branch0 m -> Branch0 m)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Set Symbol -> [Symbol]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Set Symbol -> [(Path, Branch0 m -> Branch0 m)])
-> Set Symbol -> [(Path, Branch0 m -> Branch0 m)]
forall a b. (a -> b) -> a -> b
$
        SlurpComponent -> Set Symbol
SC.terms SlurpComponent
slurp Set Symbol -> Set Symbol -> Set Symbol
forall a. Semigroup a => a -> a -> a
<> Set Symbol -> TypecheckedUnisonFile Symbol Ann -> Set Symbol
forall v a. Ord v => Set v -> TypecheckedUnisonFile v a -> Set v
UF.constructorsForDecls (SlurpComponent -> Set Symbol
SC.types SlurpComponent
slurp) TypecheckedUnisonFile Symbol Ann
uf
    names :: Names
names = TypecheckedUnisonFile Symbol Ann -> Names
forall v a. Var v => TypecheckedUnisonFile v a -> Names
UF.typecheckedToNames TypecheckedUnisonFile Symbol Ann
uf
    doTerm :: Symbol -> (Path, Branch0 m -> Branch0 m)
    doTerm :: Symbol -> (Path, Branch0 m -> Branch0 m)
doTerm Symbol
v = case Set Referent -> [Referent]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Names -> Name -> Set Referent
Names.termsNamed Names
names (Symbol -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar Symbol
v)) of
      [] -> Symbol -> (Path, Branch0 m -> Branch0 m)
errorMissingVar Symbol
v
      [Referent
r] ->
        let split :: Split Path
split = Name -> Split Path
Path.splitFromName (Symbol -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar Symbol
v)
         in Split Path -> Referent -> (Path, Branch0 m -> Branch0 m)
forall p (m :: * -> *).
Split p -> Referent -> (p, Branch0 m -> Branch0 m)
BranchUtil.makeAddTermName Split Path
split Referent
r
      [Referent]
wha ->
        [Char] -> (Path, Branch0 m -> Branch0 m)
forall a. HasCallStack => [Char] -> a
error ([Char] -> (Path, Branch0 m -> Branch0 m))
-> [Char] -> (Path, Branch0 m -> Branch0 m)
forall a b. (a -> b) -> a -> b
$
          [Char]
"Unison bug, typechecked file w/ multiple terms named "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Symbol -> [Char]
forall v. Var v => v -> [Char]
Var.nameStr Symbol
v
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
": "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Referent] -> [Char]
forall a. Show a => a -> [Char]
show [Referent]
wha
    doType :: Symbol -> (Path, Branch0 m -> Branch0 m)
    doType :: Symbol -> (Path, Branch0 m -> Branch0 m)
doType Symbol
v = case Set TypeReference -> [TypeReference]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Names -> Name -> Set TypeReference
Names.typesNamed Names
names (Symbol -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar Symbol
v)) of
      [] -> Symbol -> (Path, Branch0 m -> Branch0 m)
errorMissingVar Symbol
v
      [TypeReference
r] ->
        let split :: Split Path
split = Name -> Split Path
Path.splitFromName (Symbol -> Name
forall v. Var v => v -> Name
Name.unsafeParseVar Symbol
v)
         in Split Path -> TypeReference -> (Path, Branch0 m -> Branch0 m)
forall p (m :: * -> *).
Split p -> TypeReference -> (p, Branch0 m -> Branch0 m)
BranchUtil.makeAddTypeName Split Path
split TypeReference
r
      [TypeReference]
wha ->
        [Char] -> (Path, Branch0 m -> Branch0 m)
forall a. HasCallStack => [Char] -> a
error ([Char] -> (Path, Branch0 m -> Branch0 m))
-> [Char] -> (Path, Branch0 m -> Branch0 m)
forall a b. (a -> b) -> a -> b
$
          [Char]
"Unison bug, typechecked file w/ multiple types named "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> Symbol -> [Char]
forall v. Var v => v -> [Char]
Var.nameStr Symbol
v
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
": "
            [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [TypeReference] -> [Char]
forall a. Show a => a -> [Char]
show [TypeReference]
wha
    errorMissingVar :: Symbol -> (Path, Branch0 m -> Branch0 m)
errorMissingVar Symbol
v = [Char] -> (Path, Branch0 m -> Branch0 m)
forall a. HasCallStack => [Char] -> a
error ([Char] -> (Path, Branch0 m -> Branch0 m))
-> [Char] -> (Path, Branch0 m -> Branch0 m)
forall a b. (a -> b) -> a -> b
$ [Char]
"expected to find " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Symbol -> [Char]
forall a. Show a => a -> [Char]
show Symbol
v [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
" in " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ TypecheckedUnisonFile Symbol Ann -> [Char]
forall a. Show a => a -> [Char]
show TypecheckedUnisonFile Symbol Ann
uf