{-# 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.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

type Error = P.Pretty P.ColorText

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 v = Runtime
  { forall v. Runtime v -> IO ()
terminate :: IO (),
    forall v.
Runtime v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> Term v
-> IO (Either Error ([Error], Term v))
evaluate ::
      CL.CodeLookup v IO () ->
      PPE.PrettyPrintEnv ->
      Term v ->
      IO (Either Error ([Error], Term v)),
    forall v.
Runtime v
-> CompileOpts
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> Reference
-> FilePath
-> IO (Maybe Error)
compileTo ::
      CompileOpts ->
      CL.CodeLookup v IO () ->
      PPE.PrettyPrintEnv ->
      Reference ->
      FilePath ->
      IO (Maybe Error),
    forall v. Runtime v -> Type v Ann
mainType :: Type v Ann,
    forall v. Runtime 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 v a =
  ( Either
      Error
      -- Bindings:
      ( [(v, Term v)],
        -- Map watchName (loc, hash, expression, value, isHit)
        [Error],
        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 v a.
  (Var v) =>
  CL.CodeLookup v IO a ->
  PPE.PrettyPrintEnv ->
  (Reference.Id -> IO (Maybe (Term v))) ->
  Runtime v ->
  TypecheckedUnisonFile v a ->
  IO (WatchResults v a)
evaluateWatches :: forall v a.
Var v =>
CodeLookup v IO a
-> PrettyPrintEnv
-> (Id -> IO (Maybe (Term v)))
-> Runtime v
-> TypecheckedUnisonFile v a
-> IO (WatchResults v a)
evaluateWatches CodeLookup v IO a
code PrettyPrintEnv
ppe Id -> IO (Maybe (Term2 v () () v ()))
evaluationCache Runtime 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 Error ([Error], Term2 v () () v ())
out <- Runtime v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> Term2 v () () v ()
-> IO (Either Error ([Error], Term2 v () () v ()))
forall v.
Runtime v
-> CodeLookup v IO ()
-> PrettyPrintEnv
-> Term v
-> IO (Either Error ([Error], Term v))
evaluate Runtime v
rt CodeLookup v IO ()
cl PrettyPrintEnv
ppe Term2 v () () v ()
bigOl'LetRec
  case Either Error ([Error], Term2 v () () v ())
out of
    Right ([Error]
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 v a -> IO (WatchResults v a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (WatchResults v a -> IO (WatchResults v a))
-> WatchResults v a -> IO (WatchResults v a)
forall a b. (a -> b) -> a -> b
$ ([(v, Term2 v () () v ())], [Error],
 Map
   v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool))
-> WatchResults v a
forall a b. b -> Either a b
Right ([(v, Term2 v () () v ())]
bindings, [Error]
errs, Map
  v (a, FilePath, Id, Term2 v () () v (), Term2 v () () v (), Bool)
watchMap)
    Left Error
e -> WatchResults v a -> IO (WatchResults v a)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Error -> WatchResults v a
forall a b. a -> Either a b
Left Error
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 ->
  Runtime v ->
  Term.Term v a ->
  IO (Either Error ([Error], Term v))
evaluateTerm' :: forall v a.
(Var v, Monoid a) =>
CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> Runtime v
-> Term v a
-> IO (Either Error ([Error], Term v))
evaluateTerm' CodeLookup v IO a
codeLookup Id -> IO (Maybe (Term v))
cache PrettyPrintEnv
ppe Runtime 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 Error ([Error], Term v)
-> IO (Either Error ([Error], Term v))
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (([Error], Term v) -> Either Error ([Error], Term v)
forall a b. b -> Either a b
Right ([], 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 v -> Term F v Ann
forall v. Runtime v -> Type v Ann
mainType Runtime v
rt)])]
      WatchResults v ()
r <- CodeLookup v IO ()
-> PrettyPrintEnv
-> (Id -> IO (Maybe (Term v)))
-> Runtime v
-> TypecheckedUnisonFile v ()
-> IO (WatchResults v ())
forall v a.
Var v =>
CodeLookup v IO a
-> PrettyPrintEnv
-> (Id -> IO (Maybe (Term v)))
-> Runtime v
-> TypecheckedUnisonFile v a
-> IO (WatchResults 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 Id -> IO (Maybe (Term v))
cache Runtime v
rt (TypecheckedUnisonFile v a -> TypecheckedUnisonFile v ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void TypecheckedUnisonFile v a
tuf)
      pure $
        WatchResults v ()
r WatchResults v ()
-> (([(v, Term v)], [Error],
     Map v ((), FilePath, Id, Term v, Term v, Bool))
    -> ([Error], Term v))
-> Either Error ([Error], Term v)
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \([(v, Term v)]
_, [Error]
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)] -> ([Error]
errs, Term v
value)
            [((), FilePath, Id, Term v, Term v, Bool)]
_ -> FilePath -> ([Error], 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 ->
  Runtime v ->
  Term.Term v a ->
  IO (Either Error ([Error], Term v))
evaluateTerm :: forall v a.
(Var v, Monoid a) =>
CodeLookup v IO a
-> PrettyPrintEnv
-> Runtime v
-> Term v a
-> IO (Either Error ([Error], Term v))
evaluateTerm CodeLookup v IO a
codeLookup = CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> Runtime v
-> Term v a
-> IO (Either Error ([Error], Term v))
forall v a.
(Var v, Monoid a) =>
CodeLookup v IO a
-> (Id -> IO (Maybe (Term v)))
-> PrettyPrintEnv
-> Runtime v
-> Term v a
-> IO (Either Error ([Error], Term v))
evaluateTerm' CodeLookup v IO a
codeLookup Id -> IO (Maybe (Term v))
forall v. Id -> IO (Maybe (Term v))
noCache