module Unison.Codebase.Editor.SlurpComponent
(
SlurpComponent (..),
empty,
fromTerms,
fromTypes,
fromCtors,
isEmpty,
difference,
intersection,
closeWithDependencies,
)
where
import Data.Map qualified as Map
import Data.Set qualified as Set
import Data.Tuple (swap)
import Unison.DataDeclaration qualified as DD
import Unison.Prelude hiding (empty)
import Unison.Reference (TypeReference)
import Unison.Symbol (Symbol)
import Unison.Term qualified as Term
import Unison.UnisonFile (TypecheckedUnisonFile)
import Unison.UnisonFile qualified as UF
import Unison.Util.Defns (Defns (..))
data SlurpComponent = SlurpComponent
{ SlurpComponent -> Set Symbol
types :: Set Symbol,
SlurpComponent -> Set Symbol
terms :: Set Symbol,
SlurpComponent -> Set Symbol
ctors :: Set Symbol
}
deriving (SlurpComponent -> SlurpComponent -> Bool
(SlurpComponent -> SlurpComponent -> Bool)
-> (SlurpComponent -> SlurpComponent -> Bool) -> Eq SlurpComponent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SlurpComponent -> SlurpComponent -> Bool
== :: SlurpComponent -> SlurpComponent -> Bool
$c/= :: SlurpComponent -> SlurpComponent -> Bool
/= :: SlurpComponent -> SlurpComponent -> Bool
Eq, (forall x. SlurpComponent -> Rep SlurpComponent x)
-> (forall x. Rep SlurpComponent x -> SlurpComponent)
-> Generic SlurpComponent
forall x. Rep SlurpComponent x -> SlurpComponent
forall x. SlurpComponent -> Rep SlurpComponent x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. SlurpComponent -> Rep SlurpComponent x
from :: forall x. SlurpComponent -> Rep SlurpComponent x
$cto :: forall x. Rep SlurpComponent x -> SlurpComponent
to :: forall x. Rep SlurpComponent x -> SlurpComponent
Generic, Eq SlurpComponent
Eq SlurpComponent =>
(SlurpComponent -> SlurpComponent -> Ordering)
-> (SlurpComponent -> SlurpComponent -> Bool)
-> (SlurpComponent -> SlurpComponent -> Bool)
-> (SlurpComponent -> SlurpComponent -> Bool)
-> (SlurpComponent -> SlurpComponent -> Bool)
-> (SlurpComponent -> SlurpComponent -> SlurpComponent)
-> (SlurpComponent -> SlurpComponent -> SlurpComponent)
-> Ord SlurpComponent
SlurpComponent -> SlurpComponent -> Bool
SlurpComponent -> SlurpComponent -> Ordering
SlurpComponent -> SlurpComponent -> SlurpComponent
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
$ccompare :: SlurpComponent -> SlurpComponent -> Ordering
compare :: SlurpComponent -> SlurpComponent -> Ordering
$c< :: SlurpComponent -> SlurpComponent -> Bool
< :: SlurpComponent -> SlurpComponent -> Bool
$c<= :: SlurpComponent -> SlurpComponent -> Bool
<= :: SlurpComponent -> SlurpComponent -> Bool
$c> :: SlurpComponent -> SlurpComponent -> Bool
> :: SlurpComponent -> SlurpComponent -> Bool
$c>= :: SlurpComponent -> SlurpComponent -> Bool
>= :: SlurpComponent -> SlurpComponent -> Bool
$cmax :: SlurpComponent -> SlurpComponent -> SlurpComponent
max :: SlurpComponent -> SlurpComponent -> SlurpComponent
$cmin :: SlurpComponent -> SlurpComponent -> SlurpComponent
min :: SlurpComponent -> SlurpComponent -> SlurpComponent
Ord, Int -> SlurpComponent -> ShowS
[SlurpComponent] -> ShowS
SlurpComponent -> String
(Int -> SlurpComponent -> ShowS)
-> (SlurpComponent -> String)
-> ([SlurpComponent] -> ShowS)
-> Show SlurpComponent
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SlurpComponent -> ShowS
showsPrec :: Int -> SlurpComponent -> ShowS
$cshow :: SlurpComponent -> String
show :: SlurpComponent -> String
$cshowList :: [SlurpComponent] -> ShowS
showList :: [SlurpComponent] -> ShowS
Show)
isEmpty :: SlurpComponent -> Bool
isEmpty :: SlurpComponent -> Bool
isEmpty SlurpComponent
sc = Set Symbol -> Bool
forall a. Set a -> Bool
Set.null SlurpComponent
sc.types Bool -> Bool -> Bool
&& Set Symbol -> Bool
forall a. Set a -> Bool
Set.null SlurpComponent
sc.terms Bool -> Bool -> Bool
&& Set Symbol -> Bool
forall a. Set a -> Bool
Set.null SlurpComponent
sc.ctors
empty :: SlurpComponent
empty :: SlurpComponent
empty = SlurpComponent {$sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
forall a. Set a
Set.empty, $sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
forall a. Set a
Set.empty, $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
forall a. Set a
Set.empty}
difference :: SlurpComponent -> SlurpComponent -> SlurpComponent
difference :: SlurpComponent -> SlurpComponent -> SlurpComponent
difference SlurpComponent
c1 SlurpComponent
c2 = SlurpComponent {$sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
types', $sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
terms', $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
ctors'}
where
types' :: Set Symbol
types' = SlurpComponent
c1.types Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.difference` SlurpComponent
c2.types
terms' :: Set Symbol
terms' = SlurpComponent
c1.terms Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.difference` SlurpComponent
c2.terms
ctors' :: Set Symbol
ctors' = SlurpComponent
c1.ctors Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.difference` SlurpComponent
c2.ctors
intersection :: SlurpComponent -> SlurpComponent -> SlurpComponent
intersection :: SlurpComponent -> SlurpComponent -> SlurpComponent
intersection SlurpComponent
c1 SlurpComponent
c2 = SlurpComponent {$sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
types', $sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
terms', $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
ctors'}
where
types' :: Set Symbol
types' = SlurpComponent
c1.types Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` SlurpComponent
c2.types
terms' :: Set Symbol
terms' = SlurpComponent
c1.terms Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` SlurpComponent
c2.terms
ctors' :: Set Symbol
ctors' = SlurpComponent
c1.ctors Set Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => Set a -> Set a -> Set a
`Set.intersection` SlurpComponent
c2.ctors
instance Semigroup SlurpComponent where
SlurpComponent
c1 <> :: SlurpComponent -> SlurpComponent -> SlurpComponent
<> SlurpComponent
c2 =
SlurpComponent
{ $sel:types:SlurpComponent :: Set Symbol
types = SlurpComponent
c1.types Set Symbol -> Set Symbol -> Set Symbol
forall a. Semigroup a => a -> a -> a
<> SlurpComponent
c2.types,
$sel:terms:SlurpComponent :: Set Symbol
terms = SlurpComponent
c1.terms Set Symbol -> Set Symbol -> Set Symbol
forall a. Semigroup a => a -> a -> a
<> SlurpComponent
c2.terms,
$sel:ctors:SlurpComponent :: Set Symbol
ctors = SlurpComponent
c1.ctors Set Symbol -> Set Symbol -> Set Symbol
forall a. Semigroup a => a -> a -> a
<> SlurpComponent
c2.ctors
}
instance Monoid SlurpComponent where
mempty :: SlurpComponent
mempty = SlurpComponent
empty
closeWithDependencies ::
forall a.
TypecheckedUnisonFile Symbol a ->
SlurpComponent ->
SlurpComponent
closeWithDependencies :: forall a.
TypecheckedUnisonFile Symbol a -> SlurpComponent -> SlurpComponent
closeWithDependencies TypecheckedUnisonFile Symbol a
uf SlurpComponent
inputs = SlurpComponent
seenDefns {ctors = constructorDeps}
where
seenDefns :: SlurpComponent
seenDefns = (SlurpComponent -> Symbol -> SlurpComponent)
-> SlurpComponent -> Set Symbol -> SlurpComponent
forall b a. (b -> a -> b) -> b -> Set a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SlurpComponent -> Symbol -> SlurpComponent
termDeps (SlurpComponent {$sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
forall a. Monoid a => a
mempty, $sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
seenTypes, $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
forall a. Monoid a => a
mempty}) SlurpComponent
inputs.terms
seenTypes :: Set Symbol
seenTypes = (Set Symbol -> Symbol -> Set Symbol)
-> Set Symbol -> Set Symbol -> Set Symbol
forall b a. (b -> a -> b) -> b -> Set a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Set Symbol -> Symbol -> Set Symbol
typeDeps Set Symbol
forall a. Monoid a => a
mempty SlurpComponent
inputs.types
constructorDeps :: Set Symbol
constructorDeps :: Set Symbol
constructorDeps = Set Symbol -> TypecheckedUnisonFile Symbol a -> Set Symbol
forall v a. Ord v => Set v -> TypecheckedUnisonFile v a -> Set v
UF.constructorsForDecls Set Symbol
seenTypes TypecheckedUnisonFile Symbol a
uf
termDeps :: SlurpComponent -> Symbol -> SlurpComponent
termDeps :: SlurpComponent -> Symbol -> SlurpComponent
termDeps SlurpComponent
seen Symbol
v | Symbol -> Set Symbol -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Symbol
v SlurpComponent
seen.terms = SlurpComponent
seen
termDeps SlurpComponent
seen Symbol
v = SlurpComponent -> Maybe SlurpComponent -> SlurpComponent
forall a. a -> Maybe a -> a
fromMaybe SlurpComponent
seen do
Term Symbol a
term <- Symbol -> Maybe (Term Symbol a)
findTerm Symbol
v
let
tdeps :: [Symbol]
tdeps :: [Symbol]
tdeps = Set TypeReference -> [Symbol]
resolveTypes (Term Symbol a -> DefnsF Set TypeReference TypeReference
forall v vt at ap a.
(Ord v, Ord vt) =>
Term2 vt at ap v a -> DefnsF Set TypeReference TypeReference
Term.dependencies Term Symbol a
term).types
seenTypes :: Set Symbol
seenTypes :: Set Symbol
seenTypes = (Set Symbol -> Symbol -> Set Symbol)
-> Set Symbol -> [Symbol] -> Set Symbol
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Set Symbol -> Symbol -> Set Symbol
typeDeps SlurpComponent
seen.types [Symbol]
tdeps
seenTerms :: Set Symbol
seenTerms = Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => a -> Set a -> Set a
Set.insert Symbol
v SlurpComponent
seen.terms
SlurpComponent -> Maybe SlurpComponent
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SlurpComponent -> Maybe SlurpComponent)
-> SlurpComponent -> Maybe SlurpComponent
forall a b. (a -> b) -> a -> b
$
(SlurpComponent -> Symbol -> SlurpComponent)
-> SlurpComponent -> Set Symbol -> SlurpComponent
forall b a. (b -> a -> b) -> b -> Set a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl'
SlurpComponent -> Symbol -> SlurpComponent
termDeps
( SlurpComponent
seen
SlurpComponent
-> (SlurpComponent -> SlurpComponent) -> SlurpComponent
forall a b. a -> (a -> b) -> b
& ASetter SlurpComponent SlurpComponent (Set Symbol) (Set Symbol)
#types ASetter SlurpComponent SlurpComponent (Set Symbol) (Set Symbol)
-> Set Symbol -> SlurpComponent -> SlurpComponent
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Set Symbol
seenTypes
SlurpComponent
-> (SlurpComponent -> SlurpComponent) -> SlurpComponent
forall a b. a -> (a -> b) -> b
& ASetter SlurpComponent SlurpComponent (Set Symbol) (Set Symbol)
#terms ASetter SlurpComponent SlurpComponent (Set Symbol) (Set Symbol)
-> Set Symbol -> SlurpComponent -> SlurpComponent
forall s t a b. ASetter s t a b -> b -> s -> t
.~ Set Symbol
seenTerms
)
(Term Symbol a -> Set Symbol
forall vt v a. Term' vt v a -> Set v
Term.freeVars Term Symbol a
term)
typeDeps :: Set Symbol -> Symbol -> Set Symbol
typeDeps :: Set Symbol -> Symbol -> Set Symbol
typeDeps Set Symbol
seen Symbol
v | Symbol -> Set Symbol -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Symbol
v Set Symbol
seen = Set Symbol
seen
typeDeps Set Symbol
seen Symbol
v = Set Symbol -> Maybe (Set Symbol) -> Set Symbol
forall a. a -> Maybe a -> a
fromMaybe Set Symbol
seen (Maybe (Set Symbol) -> Set Symbol)
-> Maybe (Set Symbol) -> Set Symbol
forall a b. (a -> b) -> a -> b
$ do
DataDeclaration Symbol a
dd <-
((TypeReference, DataDeclaration Symbol a)
-> DataDeclaration Symbol a)
-> Maybe (TypeReference, DataDeclaration Symbol a)
-> Maybe (DataDeclaration Symbol a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (TypeReference, DataDeclaration Symbol a)
-> DataDeclaration Symbol a
forall a b. (a, b) -> b
snd (Symbol
-> Map Symbol (TypeReference, DataDeclaration Symbol a)
-> Maybe (TypeReference, DataDeclaration Symbol a)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Symbol
v (TypecheckedUnisonFile Symbol a
-> Map Symbol (TypeReference, DataDeclaration Symbol a)
forall v a.
TypecheckedUnisonFile v a
-> Map v (TypeReference, DataDeclaration v a)
UF.dataDeclarations' TypecheckedUnisonFile Symbol a
uf))
Maybe (DataDeclaration Symbol a)
-> Maybe (DataDeclaration Symbol a)
-> Maybe (DataDeclaration Symbol a)
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ((TypeReference, EffectDeclaration Symbol a)
-> DataDeclaration Symbol a)
-> Maybe (TypeReference, EffectDeclaration Symbol a)
-> Maybe (DataDeclaration Symbol a)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (EffectDeclaration Symbol a -> DataDeclaration Symbol a
forall v a. EffectDeclaration v a -> DataDeclaration v a
DD.toDataDecl (EffectDeclaration Symbol a -> DataDeclaration Symbol a)
-> ((TypeReference, EffectDeclaration Symbol a)
-> EffectDeclaration Symbol a)
-> (TypeReference, EffectDeclaration Symbol a)
-> DataDeclaration Symbol a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TypeReference, EffectDeclaration Symbol a)
-> EffectDeclaration Symbol a
forall a b. (a, b) -> b
snd) (Symbol
-> Map Symbol (TypeReference, EffectDeclaration Symbol a)
-> Maybe (TypeReference, EffectDeclaration Symbol a)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Symbol
v (TypecheckedUnisonFile Symbol a
-> Map Symbol (TypeReference, EffectDeclaration Symbol a)
forall v a.
TypecheckedUnisonFile v a
-> Map v (TypeReference, EffectDeclaration v a)
UF.effectDeclarations' TypecheckedUnisonFile Symbol a
uf))
pure $ (Set Symbol -> Symbol -> Set Symbol)
-> Set Symbol -> [Symbol] -> Set Symbol
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Set Symbol -> Symbol -> Set Symbol
typeDeps (Symbol -> Set Symbol -> Set Symbol
forall a. Ord a => a -> Set a -> Set a
Set.insert Symbol
v Set Symbol
seen) (Set TypeReference -> [Symbol]
resolveTypes (Set TypeReference -> [Symbol]) -> Set TypeReference -> [Symbol]
forall a b. (a -> b) -> a -> b
$ DataDeclaration Symbol a -> Set TypeReference
forall v a. Ord v => DataDeclaration v a -> Set TypeReference
DD.typeDependencies DataDeclaration Symbol a
dd)
resolveTypes :: Set TypeReference -> [Symbol]
resolveTypes :: Set TypeReference -> [Symbol]
resolveTypes Set TypeReference
rs = [Symbol
v | TypeReference
r <- Set TypeReference -> [TypeReference]
forall a. Set a -> [a]
Set.toList Set TypeReference
rs, Just Symbol
v <- [TypeReference -> Map TypeReference Symbol -> Maybe Symbol
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup TypeReference
r Map TypeReference Symbol
typeNames]]
findTerm :: Symbol -> Maybe (Term.Term Symbol a)
findTerm :: Symbol -> Maybe (Term Symbol a)
findTerm Symbol
v = Symbol -> Map Symbol (Term Symbol a) -> Maybe (Term Symbol a)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Symbol
v Map Symbol (Term Symbol a)
allTerms
allTerms :: Map Symbol (Term Symbol a)
allTerms = TypecheckedUnisonFile Symbol a -> Map Symbol (Term Symbol a)
forall v a. Ord v => TypecheckedUnisonFile v a -> Map v (Term v a)
UF.allTerms TypecheckedUnisonFile Symbol a
uf
typeNames :: Map TypeReference Symbol
typeNames :: Map TypeReference Symbol
typeNames = Map Symbol TypeReference -> Map TypeReference Symbol
forall k v. (Ord k, Ord v) => Map k v -> Map v k
invert ((TypeReference, DataDeclaration Symbol a) -> TypeReference
forall a b. (a, b) -> a
fst ((TypeReference, DataDeclaration Symbol a) -> TypeReference)
-> Map Symbol (TypeReference, DataDeclaration Symbol a)
-> Map Symbol TypeReference
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypecheckedUnisonFile Symbol a
-> Map Symbol (TypeReference, DataDeclaration Symbol a)
forall v a.
TypecheckedUnisonFile v a
-> Map v (TypeReference, DataDeclaration v a)
UF.dataDeclarations' TypecheckedUnisonFile Symbol a
uf) Map TypeReference Symbol
-> Map TypeReference Symbol -> Map TypeReference Symbol
forall a. Semigroup a => a -> a -> a
<> Map Symbol TypeReference -> Map TypeReference Symbol
forall k v. (Ord k, Ord v) => Map k v -> Map v k
invert ((TypeReference, EffectDeclaration Symbol a) -> TypeReference
forall a b. (a, b) -> a
fst ((TypeReference, EffectDeclaration Symbol a) -> TypeReference)
-> Map Symbol (TypeReference, EffectDeclaration Symbol a)
-> Map Symbol TypeReference
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TypecheckedUnisonFile Symbol a
-> Map Symbol (TypeReference, EffectDeclaration Symbol a)
forall v a.
TypecheckedUnisonFile v a
-> Map v (TypeReference, EffectDeclaration v a)
UF.effectDeclarations' TypecheckedUnisonFile Symbol a
uf)
invert :: forall k v. (Ord k) => (Ord v) => Map k v -> Map v k
invert :: forall k v. (Ord k, Ord v) => Map k v -> Map v k
invert Map k v
m = [(v, k)] -> Map v k
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ((k, v) -> (v, k)
forall a b. (a, b) -> (b, a)
swap ((k, v) -> (v, k)) -> [(k, v)] -> [(v, k)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map k v -> [(k, v)]
forall k a. Map k a -> [(k, a)]
Map.toList Map k v
m)
fromTypes :: Set Symbol -> SlurpComponent
fromTypes :: Set Symbol -> SlurpComponent
fromTypes Set Symbol
vs = SlurpComponent {$sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
forall a. Set a
Set.empty, $sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
vs, $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
forall a. Set a
Set.empty}
fromTerms :: Set Symbol -> SlurpComponent
fromTerms :: Set Symbol -> SlurpComponent
fromTerms Set Symbol
vs = SlurpComponent {$sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
vs, $sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
forall a. Set a
Set.empty, $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
forall a. Set a
Set.empty}
fromCtors :: Set Symbol -> SlurpComponent
fromCtors :: Set Symbol -> SlurpComponent
fromCtors Set Symbol
vs = SlurpComponent {$sel:terms:SlurpComponent :: Set Symbol
terms = Set Symbol
forall a. Set a
Set.empty, $sel:types:SlurpComponent :: Set Symbol
types = Set Symbol
forall a. Set a
Set.empty, $sel:ctors:SlurpComponent :: Set Symbol
ctors = Set Symbol
vs}