module Unison.Codebase.Editor.HandleInput.TermResolution ( lookupTermRefs, resolveCon, resolveTerm, resolveTermRef, resolveMainRef, ) where import Control.Monad.Reader (ask) import Data.Set qualified as Set import Unison.Cli.Monad (Cli) import Unison.Cli.Monad qualified as Cli import Unison.Cli.NamesUtils qualified as Cli import Unison.Codebase qualified as Codebase import Unison.Codebase.Editor.Output (NumberedOutput (..), Output (..)) import Unison.Codebase.MainTerm qualified as MainTerm import Unison.Codebase.Path qualified as Path import Unison.Codebase.Runtime qualified as Runtime import Unison.ConstructorReference import Unison.HashQualified qualified as HQ import Unison.HashQualifiedPrime qualified as HQ' import Unison.Name (Name) import Unison.Names (Names) import Unison.NamesWithHistory qualified as Names import Unison.Parser.Ann (Ann) import Unison.Prelude import Unison.PrettyPrintEnv.Names qualified as PPE import Unison.PrettyPrintEnvDecl qualified as PPED import Unison.Reference (Reference, TermReference) import Unison.Referent (Referent, pattern Con, pattern Ref) import Unison.Symbol (Symbol) import Unison.Term (Term) import Unison.Type (Type) lookupTerm :: HQ.HashQualified Name -> Names -> [Referent] lookupTerm :: HashQualified Name -> Names -> [Referent] lookupTerm HashQualified Name hq Names parseNames = Set Referent -> [Referent] forall a. Set a -> [a] Set.toList (SearchType -> HashQualified Name -> Names -> Set Referent Names.lookupHQTerm SearchType Names.IncludeSuffixes HashQualified Name hq Names parseNames) lookupCon :: HQ.HashQualified Name -> Names -> ([ConstructorReference], [Referent]) lookupCon :: HashQualified Name -> Names -> ([ConstructorReference], [Referent]) lookupCon HashQualified Name hq Names parseNames = [(ConstructorReference, Referent)] -> ([ConstructorReference], [Referent]) forall a b. [(a, b)] -> ([a], [b]) unzip ([(ConstructorReference, Referent)] -> ([ConstructorReference], [Referent])) -> ([Referent] -> [(ConstructorReference, Referent)]) -> [Referent] -> ([ConstructorReference], [Referent]) forall b c a. (b -> c) -> (a -> b) -> a -> c . [Maybe (ConstructorReference, Referent)] -> [(ConstructorReference, Referent)] forall a. [Maybe a] -> [a] catMaybes ([Maybe (ConstructorReference, Referent)] -> [(ConstructorReference, Referent)]) -> ([Referent] -> [Maybe (ConstructorReference, Referent)]) -> [Referent] -> [(ConstructorReference, Referent)] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Referent -> Maybe (ConstructorReference, Referent)) -> [Referent] -> [Maybe (ConstructorReference, Referent)] forall a b. (a -> b) -> [a] -> [b] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Referent -> Maybe (ConstructorReference, Referent) extract ([Referent] -> ([ConstructorReference], [Referent])) -> [Referent] -> ([ConstructorReference], [Referent]) forall a b. (a -> b) -> a -> b $ HashQualified Name -> Names -> [Referent] lookupTerm HashQualified Name hq Names parseNames where extract :: Referent -> Maybe (ConstructorReference, Referent) extract rt :: Referent rt@(Con ConstructorReference rf ConstructorType _) = (ConstructorReference, Referent) -> Maybe (ConstructorReference, Referent) forall a. a -> Maybe a Just (ConstructorReference rf, Referent rt) extract Referent _ = Maybe (ConstructorReference, Referent) forall a. Maybe a Nothing lookupTermRefs :: HQ.HashQualified Name -> Names -> ([Reference], [Referent]) lookupTermRefs :: HashQualified Name -> Names -> ([Reference' Text Hash], [Referent]) lookupTermRefs HashQualified Name hq Names parseNames = [(Reference' Text Hash, Referent)] -> ([Reference' Text Hash], [Referent]) forall a b. [(a, b)] -> ([a], [b]) unzip ([(Reference' Text Hash, Referent)] -> ([Reference' Text Hash], [Referent])) -> ([Referent] -> [(Reference' Text Hash, Referent)]) -> [Referent] -> ([Reference' Text Hash], [Referent]) forall b c a. (b -> c) -> (a -> b) -> a -> c . [Maybe (Reference' Text Hash, Referent)] -> [(Reference' Text Hash, Referent)] forall a. [Maybe a] -> [a] catMaybes ([Maybe (Reference' Text Hash, Referent)] -> [(Reference' Text Hash, Referent)]) -> ([Referent] -> [Maybe (Reference' Text Hash, Referent)]) -> [Referent] -> [(Reference' Text Hash, Referent)] forall b c a. (b -> c) -> (a -> b) -> a -> c . (Referent -> Maybe (Reference' Text Hash, Referent)) -> [Referent] -> [Maybe (Reference' Text Hash, Referent)] forall a b. (a -> b) -> [a] -> [b] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Referent -> Maybe (Reference' Text Hash, Referent) extract ([Referent] -> ([Reference' Text Hash], [Referent])) -> [Referent] -> ([Reference' Text Hash], [Referent]) forall a b. (a -> b) -> a -> b $ HashQualified Name -> Names -> [Referent] lookupTerm HashQualified Name hq Names parseNames where extract :: Referent -> Maybe (Reference' Text Hash, Referent) extract rt :: Referent rt@(Ref Reference' Text Hash rf) = (Reference' Text Hash, Referent) -> Maybe (Reference' Text Hash, Referent) forall a. a -> Maybe a Just (Reference' Text Hash rf, Referent rt) extract Referent _ = Maybe (Reference' Text Hash, Referent) forall a. Maybe a Nothing resolveTerm :: HQ.HashQualified Name -> Cli Referent resolveTerm :: HashQualified Name -> Cli Referent resolveTerm HashQualified Name name = do Names names <- Cli Names Cli.currentNames let pped :: PrettyPrintEnvDecl pped = Namer -> Suffixifier -> PrettyPrintEnvDecl PPED.makePPED (Int -> Names -> Namer PPE.hqNamer Int 10 Names names) (Names -> Suffixifier PPE.suffixifyByHash Names names) let suffixifiedPPE :: PrettyPrintEnv suffixifiedPPE = PrettyPrintEnvDecl -> PrettyPrintEnv PPED.suffixifiedPPE PrettyPrintEnvDecl pped case HashQualified Name -> Names -> [Referent] lookupTerm HashQualified Name name Names names of [] -> Output -> Cli Referent forall a. Output -> Cli a Cli.returnEarly (Output -> Cli Referent) -> (Either ShortHash (HashQualified Name) -> Output) -> Either ShortHash (HashQualified Name) -> Cli Referent forall b c a. (b -> c) -> (a -> b) -> a -> c . (ShortHash -> Output) -> (HashQualified Name -> Output) -> Either ShortHash (HashQualified Name) -> Output forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either ShortHash -> Output TermNotFound' (HashQualified (Split Path') -> Output TermNotFound (HashQualified (Split Path') -> Output) -> (HashQualified Name -> HashQualified (Split Path')) -> HashQualified Name -> Output forall b c a. (b -> c) -> (a -> b) -> a -> c . (Name -> Split Path') -> HashQualified Name -> HashQualified (Split Path') forall a b. (a -> b) -> HashQualified a -> HashQualified b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Name -> Split Path' Path.parentOfName) (Either ShortHash (HashQualified Name) -> Cli Referent) -> Either ShortHash (HashQualified Name) -> Cli Referent forall a b. (a -> b) -> a -> b $ HashQualified Name -> Either ShortHash (HashQualified Name) forall n. HashQualified n -> HashOrHQ n HQ'.fromHQ HashQualified Name name [Referent rf] -> Referent -> Cli Referent forall a. a -> Cli a forall (f :: * -> *) a. Applicative f => a -> f a pure Referent rf [Referent] rfs -> Output -> Cli Referent forall a. Output -> Cli a Cli.returnEarly (Output -> Cli Referent) -> (Set Referent -> Output) -> Set Referent -> Cli Referent forall b c a. (b -> c) -> (a -> b) -> a -> c . PrettyPrintEnv -> HashQualified Name -> Set Referent -> Output TermAmbiguous PrettyPrintEnv suffixifiedPPE HashQualified Name name (Set Referent -> Cli Referent) -> Set Referent -> Cli Referent forall a b. (a -> b) -> a -> b $ [Referent] -> Set Referent forall a. Ord a => [a] -> Set a Set.fromList [Referent] rfs resolveCon :: HQ.HashQualified Name -> Cli ConstructorReference resolveCon :: HashQualified Name -> Cli ConstructorReference resolveCon HashQualified Name name = do Names names <- Cli Names Cli.currentNames let pped :: PrettyPrintEnvDecl pped = Namer -> Suffixifier -> PrettyPrintEnvDecl PPED.makePPED (Int -> Names -> Namer PPE.hqNamer Int 10 Names names) (Names -> Suffixifier PPE.suffixifyByHash Names names) let suffixifiedPPE :: PrettyPrintEnv suffixifiedPPE = PrettyPrintEnvDecl -> PrettyPrintEnv PPED.suffixifiedPPE PrettyPrintEnvDecl pped case HashQualified Name -> Names -> ([ConstructorReference], [Referent]) lookupCon HashQualified Name name Names names of ([], [Referent] _) -> Output -> Cli ConstructorReference forall a. Output -> Cli a Cli.returnEarly (Output -> Cli ConstructorReference) -> (Either ShortHash (HashQualified Name) -> Output) -> Either ShortHash (HashQualified Name) -> Cli ConstructorReference forall b c a. (b -> c) -> (a -> b) -> a -> c . (ShortHash -> Output) -> (HashQualified Name -> Output) -> Either ShortHash (HashQualified Name) -> Output forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either ShortHash -> Output TermNotFound' (HashQualified (Split Path') -> Output TermNotFound (HashQualified (Split Path') -> Output) -> (HashQualified Name -> HashQualified (Split Path')) -> HashQualified Name -> Output forall b c a. (b -> c) -> (a -> b) -> a -> c . (Name -> Split Path') -> HashQualified Name -> HashQualified (Split Path') forall a b. (a -> b) -> HashQualified a -> HashQualified b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Name -> Split Path' Path.parentOfName) (Either ShortHash (HashQualified Name) -> Cli ConstructorReference) -> Either ShortHash (HashQualified Name) -> Cli ConstructorReference forall a b. (a -> b) -> a -> b $ HashQualified Name -> Either ShortHash (HashQualified Name) forall n. HashQualified n -> HashOrHQ n HQ'.fromHQ HashQualified Name name ([ConstructorReference co], [Referent] _) -> ConstructorReference -> Cli ConstructorReference forall a. a -> Cli a forall (f :: * -> *) a. Applicative f => a -> f a pure ConstructorReference co ([ConstructorReference] _, [Referent] rfts) -> Output -> Cli ConstructorReference forall a. Output -> Cli a Cli.returnEarly (Output -> Cli ConstructorReference) -> (Set Referent -> Output) -> Set Referent -> Cli ConstructorReference forall b c a. (b -> c) -> (a -> b) -> a -> c . PrettyPrintEnv -> HashQualified Name -> Set Referent -> Output TermAmbiguous PrettyPrintEnv suffixifiedPPE HashQualified Name name (Set Referent -> Cli ConstructorReference) -> Set Referent -> Cli ConstructorReference forall a b. (a -> b) -> a -> b $ [Referent] -> Set Referent forall a. Ord a => [a] -> Set a Set.fromList [Referent] rfts resolveTermRef :: HQ.HashQualified Name -> Cli TermReference resolveTermRef :: HashQualified Name -> Cli (Reference' Text Hash) resolveTermRef HashQualified Name name = do Names names <- Cli Names Cli.currentNames let pped :: PrettyPrintEnvDecl pped = Namer -> Suffixifier -> PrettyPrintEnvDecl PPED.makePPED (Int -> Names -> Namer PPE.hqNamer Int 10 Names names) (Names -> Suffixifier PPE.suffixifyByHash Names names) let suffixifiedPPE :: PrettyPrintEnv suffixifiedPPE = PrettyPrintEnvDecl -> PrettyPrintEnv PPED.suffixifiedPPE PrettyPrintEnvDecl pped case HashQualified Name -> Names -> ([Reference' Text Hash], [Referent]) lookupTermRefs HashQualified Name name Names names of ([], [Referent] _) -> Output -> Cli (Reference' Text Hash) forall a. Output -> Cli a Cli.returnEarly (Output -> Cli (Reference' Text Hash)) -> (Either ShortHash (HashQualified Name) -> Output) -> Either ShortHash (HashQualified Name) -> Cli (Reference' Text Hash) forall b c a. (b -> c) -> (a -> b) -> a -> c . (ShortHash -> Output) -> (HashQualified Name -> Output) -> Either ShortHash (HashQualified Name) -> Output forall a c b. (a -> c) -> (b -> c) -> Either a b -> c either ShortHash -> Output TermNotFound' (HashQualified (Split Path') -> Output TermNotFound (HashQualified (Split Path') -> Output) -> (HashQualified Name -> HashQualified (Split Path')) -> HashQualified Name -> Output forall b c a. (b -> c) -> (a -> b) -> a -> c . (Name -> Split Path') -> HashQualified Name -> HashQualified (Split Path') forall a b. (a -> b) -> HashQualified a -> HashQualified b forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Name -> Split Path' Path.parentOfName) (Either ShortHash (HashQualified Name) -> Cli (Reference' Text Hash)) -> Either ShortHash (HashQualified Name) -> Cli (Reference' Text Hash) forall a b. (a -> b) -> a -> b $ HashQualified Name -> Either ShortHash (HashQualified Name) forall n. HashQualified n -> HashOrHQ n HQ'.fromHQ HashQualified Name name ([Reference' Text Hash rf], [Referent] _) -> Reference' Text Hash -> Cli (Reference' Text Hash) forall a. a -> Cli a forall (f :: * -> *) a. Applicative f => a -> f a pure Reference' Text Hash rf ([Reference' Text Hash] _, [Referent] rfts) -> Output -> Cli (Reference' Text Hash) forall a. Output -> Cli a Cli.returnEarly (Output -> Cli (Reference' Text Hash)) -> (Set Referent -> Output) -> Set Referent -> Cli (Reference' Text Hash) forall b c a. (b -> c) -> (a -> b) -> a -> c . PrettyPrintEnv -> HashQualified Name -> Set Referent -> Output TermAmbiguous PrettyPrintEnv suffixifiedPPE HashQualified Name name (Set Referent -> Cli (Reference' Text Hash)) -> Set Referent -> Cli (Reference' Text Hash) forall a b. (a -> b) -> a -> b $ [Referent] -> Set Referent forall a. Ord a => [a] -> Set a Set.fromList [Referent] rfts resolveMainRef :: Text -> HQ.HashQualified Name -> Cli (HQ.HashQualified Name, TermReference, Term Symbol Ann, Type Symbol Ann) resolveMainRef :: Text -> HashQualified Name -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) resolveMainRef Text what HashQualified Name mainName = do Cli.Env {Codebase IO Symbol Ann codebase :: Codebase IO Symbol Ann $sel:codebase:Env :: Env -> Codebase IO Symbol Ann codebase, Runtime Symbol runtime :: Runtime Symbol $sel:runtime:Env :: Env -> Runtime Symbol runtime} <- Cli Env forall r (m :: * -> *). MonadReader r m => m r ask let mainType :: Type Symbol Ann mainType = Runtime Symbol -> Type Symbol Ann forall e e' v. Runtime e e' v -> Type v Ann Runtime.mainType Runtime Symbol runtime Names names <- Cli Names Cli.currentNames let pped :: PrettyPrintEnvDecl pped = Namer -> Suffixifier -> PrettyPrintEnvDecl PPED.makePPED (Int -> Names -> Namer PPE.hqNamer Int 10 Names names) (Names -> Suffixifier PPE.suffixifyByHash Names names) let ppe :: PrettyPrintEnv ppe = PrettyPrintEnvDecl pped.suffixifiedPPE MainTerm Symbol mainTermResult <- (Reference' Text Hash -> Cli (Maybe (Type Symbol Ann))) -> Names -> HashQualified Name -> Type Symbol Ann -> Cli (MainTerm Symbol) forall (m :: * -> *) v. (Monad m, Var v) => (Reference' Text Hash -> m (Maybe (Type v Ann))) -> Names -> HashQualified Name -> Type v Ann -> m (MainTerm v) MainTerm.getMainTerm (IO (Maybe (Type Symbol Ann)) -> Cli (Maybe (Type Symbol Ann)) forall a. IO a -> Cli a forall (m :: * -> *) a. MonadIO m => IO a -> m a liftIO (IO (Maybe (Type Symbol Ann)) -> Cli (Maybe (Type Symbol Ann))) -> (Reference' Text Hash -> IO (Maybe (Type Symbol Ann))) -> Reference' Text Hash -> Cli (Maybe (Type Symbol Ann)) forall b c a. (b -> c) -> (a -> b) -> a -> c . Codebase IO Symbol Ann -> Transaction (Maybe (Type Symbol Ann)) -> IO (Maybe (Type Symbol Ann)) forall (m :: * -> *) v a b. MonadIO m => Codebase m v a -> Transaction b -> m b Codebase.runTransaction Codebase IO Symbol Ann codebase (Transaction (Maybe (Type Symbol Ann)) -> IO (Maybe (Type Symbol Ann))) -> (Reference' Text Hash -> Transaction (Maybe (Type Symbol Ann))) -> Reference' Text Hash -> IO (Maybe (Type Symbol Ann)) forall b c a. (b -> c) -> (a -> b) -> a -> c . Codebase IO Symbol Ann -> Reference' Text Hash -> Transaction (Maybe (Type Symbol Ann)) forall a (m :: * -> *). BuiltinAnnotation a => Codebase m Symbol a -> Reference' Text Hash -> Transaction (Maybe (Type Symbol a)) Codebase.getTypeOfTerm Codebase IO Symbol Ann codebase) Names names HashQualified Name mainName Type Symbol Ann mainType case MainTerm Symbol mainTermResult of MainTerm.Success HashQualified Name mainName1 Reference' Text Hash ref Term Symbol Ann term Type Symbol Ann ty -> (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) forall a. a -> Cli a forall (f :: * -> *) a. Applicative f => a -> f a pure (HashQualified Name mainName1, Reference' Text Hash ref, Term Symbol Ann term, Type Symbol Ann ty) MainTerm Symbol MainTerm.NotFound -> Output -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) forall a. Output -> Cli a Cli.returnEarly (HashQualified Name -> PrettyPrintEnv -> [Type Symbol Ann] -> Output NoMainFunction HashQualified Name mainName PrettyPrintEnv ppe [Type Symbol Ann mainType]) MainTerm.BadType [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] terms -> Output -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) forall a. Output -> Cli a Cli.returnEarly (Output -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann)) -> Output -> Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) forall a b. (a -> b) -> a -> b $ Text -> [(HashQualified Name, Type Symbol Ann)] -> PrettyPrintEnv -> [Type Symbol Ann] -> Output BadMainFunction Text what (((HashQualified Name, Reference' Text Hash, Type Symbol Ann) -> (HashQualified Name, Type Symbol Ann)) -> [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] -> [(HashQualified Name, Type Symbol Ann)] forall a b. (a -> b) -> [a] -> [b] map (\(HashQualified Name s, Reference' Text Hash _, Type Symbol Ann t) -> (HashQualified Name s, Type Symbol Ann t)) [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] terms) PrettyPrintEnv ppe [Type Symbol Ann mainType] MainTerm.Ambiguous [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] terms -> do NumberedOutput -> Cli () Cli.respondNumbered (NumberedOutput -> Cli ()) -> NumberedOutput -> Cli () forall a b. (a -> b) -> a -> b $ Text -> [(HashQualified Name, Type Symbol Ann)] -> PrettyPrintEnv -> NumberedOutput AmbiguousMainFunction Text what (((HashQualified Name, Reference' Text Hash, Type Symbol Ann) -> (HashQualified Name, Type Symbol Ann)) -> [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] -> [(HashQualified Name, Type Symbol Ann)] forall a b. (a -> b) -> [a] -> [b] map (\(HashQualified Name s, Reference' Text Hash _, Type Symbol Ann t) -> (HashQualified Name s, Type Symbol Ann t)) [(HashQualified Name, Reference' Text Hash, Type Symbol Ann)] terms) PrettyPrintEnv ppe Cli (HashQualified Name, Reference' Text Hash, Term Symbol Ann, Type Symbol Ann) forall a. Cli a Cli.returnEarlyWithoutOutput