{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}

module Unison.Codebase.Runtime where

import Data.Map qualified as Map
import Data.Set.NonEmpty (NESet)
import Unison.ABT qualified as ABT
import Unison.Builtin.Decls (tupleTerm, pattern TupleTerm')
import Unison.Codebase.CodeLookup qualified as CL
import Unison.Codebase.CodeLookup.Util qualified as CL
import Unison.Codebase.Runtime.Profile
import Unison.Hashing.V2.Convert qualified as Hashing
import Unison.Parser.Ann (Ann)
import Unison.Prelude
import Unison.PrettyPrintEnv qualified as PPE
import Unison.Reference (Reference)
import Unison.Reference qualified as Reference
import Unison.Term qualified as Term
import Unison.Type (Type)
import Unison.UnisonFile (TypecheckedUnisonFile)
import Unison.UnisonFile qualified as UF
import Unison.Util.Pretty qualified as P
import Unison.Var (Var)
import Unison.Var qualified as Var
import Unison.WatchKind (WatchKind)
import Unison.WatchKind qualified as WK

data Response e
  = DecompErrs [e]
  | Profile (P.Pretty P.ColorText)
  | EmptyResponse

instance Semigroup (Response e) where
  DecompErrs [e]
l <> :: Response e -> Response e -> Response e
<> DecompErrs [e]
r = [e] -> Response e
forall e. [e] -> Response e
DecompErrs ([e]
l [e] -> [e] -> [e]
forall a. Semigroup a => a -> a -> a
<> [e]
r)
  d :: Response e
d@(DecompErrs [e]
_) <> Response e
_ = Response e
d
  Response e
_ <> d :: Response e
d@(DecompErrs [e]
_) = Response e
d
  p :: Response e
p@(Profile Pretty ColorText
_) <> Response e
_ = Response e
p
  Response e
_ <> p :: Response e
p@(Profile Pretty ColorText
_) = Response e
p
  Response e
EmptyResponse <> Response e
r = Response e
r

instance Monoid (Response e) where
  mempty :: Response e
mempty = Response e
forall e. Response e
EmptyResponse

type Term v = Term.Term v ()

data CompileOpts = COpts
  { CompileOpts -> Bool
profile :: Bool
  }

defaultCompileOpts :: CompileOpts
defaultCompileOpts :: CompileOpts
defaultCompileOpts = COpts {$sel:profile:COpts :: Bool
profile = Bool
False}

data Runtime e e' v = Runtime
  { forall e e' v. Runtime e e' v -> IO ()
terminate :: IO (),
    forall e e' v.
Runtime e e' v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> ProfileSpec
-> Term v
-> IO (Either e (Response e', Term v))
evaluate ::
      CL.CodeLookup v IO () ->
      PPE.PrettyPrintEnv ->
      ProfileSpec ->
      Term v ->
      IO (Either e (Response e', Term v)),
    forall e e' v.
Runtime e e' v
-> CompileOpts
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> Reference
-> FilePath
-> IO (Maybe e)
compileTo ::
      CompileOpts ->
      CL.CodeLookup v IO () ->
      PPE.PrettyPrintEnv ->
      Reference ->
      FilePath ->
      IO (Maybe e),
    forall e e' v. Runtime e e' v -> Type v Ann
mainType :: Type v Ann,
    forall e e' v. Runtime e e' v -> NESet (Type v Ann)
ioTestTypes :: NESet (Type v Ann)
  }

type IsCacheHit = Bool

noCache :: Reference.Id -> IO (Maybe (Term v))
noCache :: forall v. Id -> IO (Maybe (Term v))
noCache Id
_ = Maybe (Term v) -> IO (Maybe (Term v))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Term v)
forall a. Maybe a
Nothing

type WatchResults e e' v a =
  Either
    e
    -- Bindings:
    ( [(v, Term v)],
      -- Map watchName (loc, hash, expression, value, isHit)
      Response e',
      Map v (a, WatchKind, Reference.Id, Term v, Term v, IsCacheHit)
    )

-- Evaluates the watch expressions in the file, returning a `Map` of their
-- results. This has to be a bit fancy to handle that the definitions in the
-- file depend on each other and evaluation must proceed in a way that respects
-- these dependencies.
--
-- Note: The definitions in the file are hashed and looked up in
-- `evaluationCache`. If that returns a result, evaluation of that definition
-- can be skipped.
evaluateWatches ::
  forall e e' v a.
  (Var v) =>
  CL.CodeLookup v IO a ->
  PPE.PrettyPrintEnv ->
  ProfileSpec ->
  (Reference.Id -> IO (Maybe (Term v))) ->
  Runtime e e' v ->
  TypecheckedUnisonFile v a ->
  IO (WatchResults e e' v a)
evaluateWatches :: forall e e' v a.
Var v =>
CodeLookup v IO a
-> PrettyPrintEnv
-> ProfileSpec
-> (Id -> IO (Maybe (Term v)))
-> Runtime e e' v
-> TypecheckedUnisonFile v a
-> IO (WatchResults e e' v a)
evaluateWatches CodeLookup v IO a
code PrettyPrintEnv
ppe ProfileSpec
prof Id -> IO (Maybe (Term2 v () () v ()))
evaluationCache Runtime e e' v
rt TypecheckedUnisonFile v a
tuf = do
  -- 1. compute hashes for everything in the file
  let m :: Map v (Reference.Id, Term.Term v a)
      m :: Map v (Id, Term v a)
m = ((a, Id, Maybe FilePath, Term v a, Type v a) -> (Id, Term v a))
-> Map v (a, Id, Maybe FilePath, Term v a, Type v a)
-> Map v (Id, Term v a)
forall a b. (a -> b) -> Map v a -> Map v b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(a
_a, Id
id, Maybe FilePath
_wk, Term v a
tm, Type v a
_tp) -> (Id
id, Term v a
tm)) (TypecheckedUnisonFile v a
-> Map v (a, Id, Maybe FilePath, Term v a, Type v a)
forall v a.
TypecheckedUnisonFile v a
-> Map v (a, Id, Maybe FilePath, Term v a, Type v a)
UF.hashTermsId TypecheckedUnisonFile v a
tuf)
      Set v
watches :: Set v = Map v FilePath -> Set v
forall k a. Map k a -> Set k
Map.keysSet Map v FilePath
watchKinds
      watchKinds :: Map v WatchKind
      watchKinds :: Map v FilePath
watchKinds =
        [(v, FilePath)] -> Map v FilePath
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
          [(v
v, FilePath
k) | (FilePath
k, [(v, a, Term v a, Type v a)]
ws) <- TypecheckedUnisonFile v a
-> [(FilePath, [(v, a, Term v a, Type v a)])]
forall v a.
TypecheckedUnisonFile v a
-> [(FilePath, [(v, a, Term v a, Type v a)])]
UF.watchComponents TypecheckedUnisonFile v a
tuf, (v
v, a
_a, Term v a
_tm, Type v a
_tp) <- [(v, a, Term v a, Type v a)]
ws]
      unann :: Term v a -> Term2 v () () v ()
unann = (a -> ()) -> Term v a -> Term2 v () () v ()
forall v a a2. Ord v => (a -> a2) -> Term v a -> Term v a2
Term.amap (() -> a -> ()
forall a b. a -> b -> a
const ())
  -- 2. use the cache to lookup things already computed
  Map v (Id, a, Term2 v () () v (), Bool)
m' <- ([(v, (Id, a, Term2 v () () v (), Bool))]
 -> Map v (Id, a, Term2 v () () v (), Bool))
-> IO [(v, (Id, a, Term2 v () () v (), Bool))]
-> IO (Map v (Id, a, Term2 v () () v (), Bool))
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [(v, (Id, a, Term2 v () () v (), Bool))]
-> Map v (Id, a, Term2 v () () v (), Bool)
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList (IO [(v, (Id, a, Term2 v () () v (), Bool))]
 -> IO (Map v (Id, a, Term2 v () () v (), Bool)))
-> (((v, (Id, Term v a))
     -> IO (v, (Id, a, Term2 v () () v (), Bool)))
    -> IO [(v, (Id, a, Term2 v () () v (), Bool))])
-> ((v, (Id, Term v a))
    -> IO (v, (Id, a, Term2 v () () v (), Bool)))
-> IO (Map v (Id, a, Term2 v () () v (), Bool))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(v, (Id, Term v a))]
-> ((v, (Id, Term v a))
    -> IO (v, (Id, a, Term2 v () () v (), Bool)))
-> IO [(v, (Id, a, Term2 v () () v (), Bool))]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for (Map v (Id, Term v a) -> [(v, (Id, Term v a))]
forall k a. Map k a -> [(k, a)]
Map.toList Map v (Id, Term v a)
m) (((v, (Id, Term v a)) -> IO (v, (Id, a, Term2 v () () v (), Bool)))
 -> IO (Map v (Id, a, Term2 v () () v (), Bool)))
-> ((v, (Id, Term v a))
    -> IO (v, (Id, a, Term2 v () () v (), Bool)))
-> IO (Map v (Id, a, Term2 v () () v (), Bool))
forall a b. (a -> b) -> a -> b
$ \(v
v, (Id
r, Term v a
t)) -> do
    Maybe (Term2 v () () v ())
o <- Id -> IO (Maybe (Term2 v () () v ()))
evaluationCache Id
r
    case Maybe (Term2 v () () v ())
o of
      Maybe (Term2 v () () v ())
Nothing -> (v, (Id, a, Term2 v () () v (), Bool))
-> IO (v, (Id, a, Term2 v () () v (), Bool))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (v
v, (Id
r, Term v a -> a
forall (f :: * -> *) v a. Term f v a -> a
ABT.annotation Term v a
t, Term v a -> Term2 v () () v ()
forall {a}. Term v a -> Term2 v () () v ()
unann Term v a
t, Bool
False))
      Just Term2 v () () v ()
t' -> (v, (Id, a, Term2 v () () v (), Bool))
-> IO (v, (Id, a, Term2 v () () v (), Bool))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (v
v, (Id
r, Term v a -> a
forall (f :: * -> *) v a. Term f v a -> a
ABT.annotation Term v a
t, Term2 v () () v ()
t', Bool
True))
  -- 3. create a big ol' let rec whose body is a big tuple of all watches
  let rv :: Map Reference.Id v
      rv :: Map Id v
rv = [(Id, v)] -> Map Id v
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Id
r, v
v) | (v
v, (Id
r, Term v a
_)) <- Map v (Id, Term v a) -> [(v, (Id, Term v a))]
forall k a. Map k a -> [(k, a)]
Map.toList Map v (Id, Term v a)
m]
      bindings :: [(v, (), Term v)]
      bindings :: [(v, (), Term2 v () () v ())]
bindings = [(v
v, (), Map Id v -> Term2 v () () v () -> Term2 v () () v ()
forall {v} {typeVar} {typeAnn} {patternAnn} {a}.
Ord v =>
Map Id v
-> Term (F typeVar typeAnn patternAnn) v a
-> Term (F typeVar typeAnn patternAnn) v a
unref Map Id v
rv Term2 v () () v ()
b) | (v
v, (Id
_, a
_, Term2 v () () v ()
b, Bool
_)) <- Map v (Id, a, Term2 v () () v (), Bool)
-> [(v, (Id, a, Term2 v () () v (), Bool))]
forall k a. Map k a -> [(k, a)]
Map.toList Map v (Id, a, Term2 v () () v (), Bool)
m']
      watchVars :: [Term2 v () () v ()]
watchVars = [() -> v -> Term2 v () () v ()
forall a v vt at ap. a -> v -> Term2 vt at ap v a
Term.var () v
v | v
v <- Set v -> [v]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set v
watches]
      bigOl'LetRec :: Term2 v () () v ()
bigOl'LetRec = Bool
-> [(v, (), Term2 v () () v ())]
-> Term2 v () () v ()
-> Term2 v () () v ()
forall v a vt.
(Ord v, Monoid a) =>
Bool -> [(v, a, Term' vt v a)] -> Term' vt v a -> Term' vt v a
Term.letRec' Bool
True [(v, (), Term2 v () () v ())]
bindings ([Term2 v () () v ()] -> Term2 v () () v ()
forall v a vt at ap.
(Var v, Monoid a) =>
[Term2 vt at ap v a] -> Term2 vt at ap v a
tupleTerm [Term2 v () () v ()]
watchVars)
      cl :: CodeLookup v IO ()
cl = CodeLookup v IO a -> CodeLookup v IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (TypecheckedUnisonFile v a -> CodeLookup v IO a
forall (m :: * -> *) v a.
(Var v, Monad m) =>
TypecheckedUnisonFile v a -> CodeLookup v m a
CL.fromTypecheckedUnisonFile TypecheckedUnisonFile v a
tuf) CodeLookup v IO () -> CodeLookup v IO () -> CodeLookup v IO ()
forall a. Semigroup a => a -> a -> a
<> CodeLookup v IO a -> CodeLookup v IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void CodeLookup v IO a
code
  -- 4. evaluate it and get all the results out of the tuple, then
  -- create the result Map
  Either e (Response e', Term2 v () () v ())
out <- Runtime e e' v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> ProfileSpec
-> Term2 v () () v ()
-> IO (Either e (Response e', Term2 v () () v ()))
forall e e' v.
Runtime e e' v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> ProfileSpec
-> Term v
-> IO (Either e (Response e', Term v))
evaluate Runtime e e' v
rt CodeLookup v IO ()
cl PrettyPrintEnv
ppe ProfileSpec
prof Term2 v () () v ()
bigOl'LetRec
  case Either e (Response e', Term2 v () () v ())
out of
    Right (Response e'
errs, Term2 v () () v ()
out) -> do
      let ([(v, Term2 v () () v ())]
bindings, [Term2 v () () v ()]
results) = case Term2 v () () v ()
out of
            TupleTerm' [Term2 v () () v ()]
results -> ([(v, Term2 v () () v ())]
forall a. Monoid a => a
mempty, [Term2 v () () v ()]
results)
            Term.LetRecNamed' [(v, Term2 v () () v ())]
bs (TupleTerm' [Term2 v () () v ()]
results) -> ([(v, Term2 v () () v ())]
bs, [Term2 v () () v ()]
results)
            Term2 v () () v ()
_ -> FilePath -> ([(v, Term2 v () () v ())], [Term2 v () () v ()])
forall a. HasCallStack => FilePath -> a
error (FilePath -> ([(v, Term2 v () () v ())], [Term2 v () () v ()]))
-> FilePath -> ([(v, Term2 v () () v ())], [Term2 v () () v ()])
forall a b. (a -> b) -> a -> b
$ FilePath
"Evaluation should produce a tuple, but gave: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Term2 v () () v () -> FilePath
forall a. Show a => a -> FilePath
show Term2 v () () v ()
out
      let go :: v
-> Term2 v () () v ()
-> (Id, a, Term2 v () () v (), Bool)
-> (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
go v
v Term2 v () () v ()
eval (Id
ref, a
a, Term2 v () () v ()
uneval, Bool
isHit) =
            ( a
a,
              FilePath -> v -> Map v FilePath -> FilePath
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault (v -> FilePath
forall {a} {a}. Show a => a -> a
die v
v) v
v Map v FilePath
watchKinds,
              Id
ref,
              Term2 v () () v ()
uneval,
              Term2 v () () v () -> Term2 v () () v ()
forall v. Ord v => Term0 v -> Term0 v
Term.etaNormalForm Term2 v () () v ()
eval,
              Bool
isHit
            )
          watchMap :: Map
  v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
watchMap =
            (v
 -> Term2 v () () v ()
 -> (Id, a, Term2 v () () v (), Bool)
 -> (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool))
-> Map v (Term2 v () () v ())
-> Map v (Id, a, Term2 v () () v (), Bool)
-> Map
     v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
forall k a b c.
Ord k =>
(k -> a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWithKey
              v
-> Term2 v () () v ()
-> (Id, a, Term2 v () () v (), Bool)
-> (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
go
              ([(v, Term2 v () () v ())] -> Map v (Term2 v () () v ())
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList (Set v -> [v]
forall a. Set a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Set v
watches [v] -> [Term2 v () () v ()] -> [(v, Term2 v () () v ())]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Term2 v () () v ()]
results))
              Map v (Id, a, Term2 v () () v (), Bool)
m'
          die :: a -> a
die a
v = FilePath -> a
forall a. HasCallStack => FilePath -> a
error (FilePath -> a) -> FilePath -> a
forall a b. (a -> b) -> a -> b
$ FilePath
"not sure what kind of watch this is: " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> a -> FilePath
forall a. Show a => a -> FilePath
show a
v
      WatchResults e e' v a -> IO (WatchResults e e' v a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WatchResults e e' v a -> IO (WatchResults e e' v a))
-> WatchResults e e' v a -> IO (WatchResults e e' v a)
forall a b. (a -> b) -> a -> b
$ ([(v, Term2 v () () v ())], Response e',
 Map
   v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool))
-> WatchResults e e' v a
forall a b. b -> Either a b
Right ([(v, Term2 v () () v ())]
bindings, Response e'
errs, Map
  v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
watchMap)
    Left e
e -> WatchResults e e' v a -> IO (WatchResults e e' v a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (e -> WatchResults e e' v a
forall a b. a -> Either a b
Left e
e)
  where
    -- unref :: Map Reference.Id v -> Term.Term v a -> Term.Term v a
    unref :: Map Id v
-> Term (F typeVar typeAnn patternAnn) v a
-> Term (F typeVar typeAnn patternAnn) v a
unref Map Id v
rv Term (F typeVar typeAnn patternAnn) v a
t = (Term (F typeVar typeAnn patternAnn) v a
 -> Maybe (Term (F typeVar typeAnn patternAnn) v a))
-> Term (F typeVar typeAnn patternAnn) v a
-> Term (F typeVar typeAnn patternAnn) v a
forall (f :: * -> *) v a.
(Traversable f, Ord v) =>
(Term f v a -> Maybe (Term f v a)) -> Term f v a -> Term f v a
ABT.visitPure Term (F typeVar typeAnn patternAnn) v a
-> Maybe (Term (F typeVar typeAnn patternAnn) v a)
go Term (F typeVar typeAnn patternAnn) v a
t
      where
        go :: Term (F typeVar typeAnn patternAnn) v a
-> Maybe (Term (F typeVar typeAnn patternAnn) v a)
go t :: Term (F typeVar typeAnn patternAnn) v a
t@(Term.Ref' (Reference.DerivedId Id
r)) = case Id -> Map Id v -> Maybe v
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Id
r Map Id v
rv of
          Maybe v
Nothing -> Maybe (Term (F typeVar typeAnn patternAnn) v a)
forall a. Maybe a
Nothing
          Just v
v -> Term (F typeVar typeAnn patternAnn) v a
-> Maybe (Term (F typeVar typeAnn patternAnn) v a)
forall a. a -> Maybe a
Just (a -> v -> Term (F typeVar typeAnn patternAnn) v a
forall a v vt at ap. a -> v -> Term2 vt at ap v a
Term.var (Term (F typeVar typeAnn patternAnn) v a -> a
forall (f :: * -> *) v a. Term f v a -> a
ABT.annotation Term (F typeVar typeAnn patternAnn) v a
t) v
v)
        go Term (F typeVar typeAnn patternAnn) v a
_ = Maybe (Term (F typeVar typeAnn patternAnn) v a)
forall a. Maybe a
Nothing

evaluateTerm' ::
  (Var v, Monoid a) =>
  CL.CodeLookup v IO a ->
  (Reference.Id -> IO (Maybe (Term v))) ->
  PPE.PrettyPrintEnv ->
  ProfileSpec ->
  Runtime e e' v ->
  Term.Term v a ->
  IO (Either e (Response e', Term v))
evaluateTerm' :: forall v a e e'.
(Var v, Monoid a) =>
CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> ProfileSpec
-> Runtime e e' v
-> Term v a
-> IO (Either e (Response e', Term v))
evaluateTerm' CodeLookup v IO a
codeLookup Id -> IO (Maybe (Term v))
cache PrettyPrintEnv
ppe ProfileSpec
prof Runtime e e' v
rt Term v a
tm = do
  Maybe (Term v)
result <- Id -> IO (Maybe (Term v))
cache (Term v a -> Id
forall v a. Var v => Term v a -> Id
Hashing.hashClosedTerm Term v a
tm)
  case Maybe (Term v)
result of
    Just Term v
r -> Either e (Response e', Term v)
-> IO (Either e (Response e', Term v))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Response e', Term v) -> Either e (Response e', Term v)
forall a b. b -> Either a b
Right (Response e'
forall e. Response e
EmptyResponse, Term v
r))
    Maybe (Term v)
Nothing -> do
      let tuf :: TypecheckedUnisonFile v a
tuf =
            Map v (Id, DataDeclaration v a)
-> Map v (Id, EffectDeclaration v a)
-> [[(v, a, Term v a, Type v a)]]
-> [(FilePath, [(v, a, Term v a, Type v a)])]
-> TypecheckedUnisonFile v a
forall v a.
Var v =>
Map v (Id, DataDeclaration v a)
-> Map v (Id, EffectDeclaration v a)
-> [[(v, a, Term v a, Type v a)]]
-> [(FilePath, [(v, a, Term v a, Type v a)])]
-> TypecheckedUnisonFile v a
UF.typecheckedUnisonFile
              Map v (Id, DataDeclaration v a)
forall a. Monoid a => a
mempty
              Map v (Id, EffectDeclaration v a)
forall a. Monoid a => a
mempty
              [[(v, a, Term v a, Type v a)]]
forall a. Monoid a => a
mempty
              [(FilePath
forall a. (Eq a, IsString a) => a
WK.RegularWatch, [(FilePath -> v
forall v. Var v => FilePath -> v
Var.nameds FilePath
"result", a
forall a. Monoid a => a
mempty, Term v a
tm, Ann -> a
forall a. Monoid a => a
mempty (Ann -> a) -> Term F v Ann -> Type v a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Runtime e e' v -> Term F v Ann
forall e e' v. Runtime e e' v -> Type v Ann
mainType Runtime e e' v
rt)])]
      WatchResults e e' v ()
r <- CodeLookup v IO ()
-> PrettyPrintEnv
-> ProfileSpec
-> (Id -> IO (Maybe (Term v)))
-> Runtime e e' v
-> TypecheckedUnisonFile v ()
-> IO (WatchResults e e' v ())
forall e e' v a.
Var v =>
CodeLookup v IO a
-> PrettyPrintEnv
-> ProfileSpec
-> (Id -> IO (Maybe (Term v)))
-> Runtime e e' v
-> TypecheckedUnisonFile v a
-> IO (WatchResults e e' v a)
evaluateWatches (CodeLookup v IO a -> CodeLookup v IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void CodeLookup v IO a
codeLookup) PrettyPrintEnv
ppe ProfileSpec
prof Id -> IO (Maybe (Term v))
cache Runtime e e' v
rt (TypecheckedUnisonFile v a -> TypecheckedUnisonFile v ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void TypecheckedUnisonFile v a
tuf)
      pure $
        WatchResults e e' v ()
r WatchResults e e' v ()
-> (([(v, Term v)], Response e',
     Map v ((), FilePath, Id, Term v, Term v, Bool))
    -> (Response e', Term v))
-> Either e (Response e', Term v)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \([(v, Term v)]
_, Response e'
errs, Map v ((), FilePath, Id, Term v, Term v, Bool)
map) ->
          case Map v ((), FilePath, Id, Term v, Term v, Bool)
-> [((), FilePath, Id, Term v, Term v, Bool)]
forall k a. Map k a -> [a]
Map.elems Map v ((), FilePath, Id, Term v, Term v, Bool)
map of
            [(()
_loc, FilePath
_kind, Id
_hash, Term v
_src, Term v
value, Bool
_isHit)] -> (Response e'
errs, Term v
value)
            [((), FilePath, Id, Term v, Term v, Bool)]
_ -> FilePath -> (Response e', Term v)
forall a. HasCallStack => FilePath -> a
error FilePath
"evaluateTerm': Pattern mismatch on watch results"

evaluateTerm ::
  (Var v, Monoid a) =>
  CL.CodeLookup v IO a ->
  PPE.PrettyPrintEnv ->
  ProfileSpec ->
  Runtime e e' v ->
  Term.Term v a ->
  IO (Either e (Response e', Term v))
evaluateTerm :: forall v a e e'.
(Var v, Monoid a) =>
CodeLookup v IO a
-> PrettyPrintEnv
-> ProfileSpec
-> Runtime e e' v
-> Term v a
-> IO (Either e (Response e', Term v))
evaluateTerm CodeLookup v IO a
codeLookup = CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> ProfileSpec
-> Runtime e e' v
-> Term v a
-> IO (Either e (Response e', Term v))
forall v a e e'.
(Var v, Monoid a) =>
CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> ProfileSpec
-> Runtime e e' v
-> Term v a
-> IO (Either e (Response e', Term v))
evaluateTerm' CodeLookup v IO a
codeLookup Id -> IO (Maybe (Term v))
forall v. Id -> IO (Maybe (Term v))
noCache