module Nix
  ( module Nix.Cache
  , module Nix.Exec
  , module Nix.Expr.Types
  , module Nix.Expr.Shorthands
  , module Nix.Expr.Types.Annotated
  , module Nix.Frames
  , module Nix.Render.Frame
  , module Nix.Normal
  , module Nix.Options
  , module Nix.String
  , module Nix.Parser
  , module Nix.Pretty
  , module Nix.Reduce
  , module Nix.Thunk
  , module Nix.Value
  , module Nix.XML
  , withNixContext
  , nixEvalExpr
  , nixEvalExprLoc
  , nixTracingEvalExprLoc
  , evaluateExpression
  , processResult
  )
where

import           Nix.Prelude
import           Relude.Unsafe                  ( (!!) )
import           GHC.Err                        ( errorWithoutStackTrace )
import           Data.Fix                       ( Fix )
import qualified Data.HashMap.Lazy             as M
import qualified Data.Text                     as Text
import qualified Data.Text.Read                as Text
import           Nix.Builtins
import           Nix.Cache
import qualified Nix.Eval                      as Eval
import           Nix.Exec
import           Nix.Expr.Types
import           Nix.Expr.Shorthands
import           Nix.Expr.Types.Annotated
import           Nix.Frames
import           Nix.String
import           Nix.Normal
import           Nix.Options
import           Nix.Parser
import           Nix.Pretty
import           Nix.Reduce
import           Nix.Render.Frame
import           Nix.Thunk
import           Nix.Value
import           Nix.Value.Monad
import           Nix.XML

-- | This is the entry point for all evaluations, whatever the expression tree
--   type. It sets up the common Nix environment and applies the
--   transformations, allowing them to be easily composed.
nixEval
  :: (MonadNix e t f m, Has e Options, Functor g)
  => Transform g (m a)
  -> Alg g (m a)
  -> Maybe Path
  -> Fix g
  -> m a
nixEval :: forall e t (f :: * -> *) (m :: * -> *) (g :: * -> *) a.
(MonadNix e t f m, Has e Options, Functor g) =>
Transform g (m a) -> Alg g (m a) -> Maybe Path -> Fix g -> m a
nixEval Transform g (m a)
transform Alg g (m a)
alg Maybe Path
mpath = forall e t (f :: * -> *) (m :: * -> *) r.
(MonadNix e t f m, Has e Options) =>
Maybe Path -> m r -> m r
withNixContext Maybe Path
mpath forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a.
Functor f =>
Transform f a -> Alg f a -> Fix f -> a
adi Transform g (m a)
transform Alg g (m a)
alg

-- | Evaluate a nix expression in the default context
nixEvalExpr
  :: (MonadNix e t f m, Has e Options)
  => Maybe Path
  -> NExpr
  -> m (NValue t f m)
nixEvalExpr :: forall e t (f :: * -> *) (m :: * -> *).
(MonadNix e t f m, Has e Options) =>
Maybe Path -> NExpr -> m (NValue t f m)
nixEvalExpr = forall e t (f :: * -> *) (m :: * -> *) (g :: * -> *) a.
(MonadNix e t f m, Has e Options, Functor g) =>
Transform g (m a) -> Alg g (m a) -> Maybe Path -> Fix g -> m a
nixEval forall a. a -> a
id forall v (m :: * -> *). MonadNixEval v m => NExprF (m v) -> m v
Eval.eval

-- | Evaluate a nix expression in the default context
nixEvalExprLoc
  :: forall e t f m
   . (MonadNix e t f m, Has e Options)
  => Maybe Path
  -> NExprLoc
  -> m (NValue t f m)
nixEvalExprLoc :: forall e t (f :: * -> *) (m :: * -> *).
(MonadNix e t f m, Has e Options) =>
Maybe Path -> NExprLoc -> m (NValue t f m)
nixEvalExprLoc =
  forall e t (f :: * -> *) (m :: * -> *) (g :: * -> *) a.
(MonadNix e t f m, Has e Options, Functor g) =>
Transform g (m a) -> Alg g (m a) -> Maybe Path -> Fix g -> m a
nixEval
    forall v (m :: * -> *) e a.
(Framed e m, Scoped v m, Has e SrcSpan, Typeable m, Typeable v) =>
TransformF NExprLoc (m a)
Eval.addMetaInfo
    forall v (m :: * -> *) ann.
MonadNixEval v m =>
AnnF ann NExprF (m v) -> m v
Eval.evalContent

-- | Evaluate a nix expression with tracing in the default context. Note that
--   this function doesn't do any tracing itself, but 'evalExprLoc' will be
--   'tracing' is set to 'True' in the Options structure (accessible through
--   'MonadNix'). All this function does is provide the right type class
--   context.
nixTracingEvalExprLoc
  :: (MonadNix e t f m, Has e Options, MonadIO m, Alternative m)
  => Maybe Path
  -> NExprLoc
  -> m (NValue t f m)
nixTracingEvalExprLoc :: forall e t (f :: * -> *) (m :: * -> *).
(MonadNix e t f m, Has e Options, MonadIO m, Alternative m) =>
Maybe Path -> NExprLoc -> m (NValue t f m)
nixTracingEvalExprLoc Maybe Path
mpath = forall e t (f :: * -> *) (m :: * -> *) r.
(MonadNix e t f m, Has e Options) =>
Maybe Path -> m r -> m r
withNixContext Maybe Path
mpath forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e t (f :: * -> *) (m :: * -> *).
MonadNix e t f m =>
NExprLoc -> m (NValue t f m)
evalExprLoc

evaluateExpression
  :: (MonadNix e t f m, Has e Options)
  => Maybe Path
  -> (Maybe Path -> NExprLoc -> m (NValue t f m))
  -> (NValue t f m -> m a)
  -> NExprLoc
  -> m a
evaluateExpression :: forall e t (f :: * -> *) (m :: * -> *) a.
(MonadNix e t f m, Has e Options) =>
Maybe Path
-> (Maybe Path -> NExprLoc -> m (NValue t f m))
-> (NValue t f m -> m a)
-> NExprLoc
-> m a
evaluateExpression Maybe Path
mpath Maybe Path -> NExprLoc -> m (NValue t f m)
evaluator NValue t f m -> m a
handler NExprLoc
expr =
  do
    Options
opts <- forall e (m :: * -> *).
(MonadReader e m, Has e Options) =>
m Options
askOptions
    (coerce :: forall a b. Coercible a b => a -> b
coerce -> [(VarName, NValue t f m)]
args) <-
      (forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse)
        NExpr -> m (NValue t f m)
eval'
        forall a b. (a -> b) -> a -> b
$  (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Text -> NExpr
parseArg forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Options -> [(Text, Text)]
getArg    Options
opts)
        forall a. Semigroup a => a -> a -> a
<> (forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Text -> NExpr
mkStr    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Options -> [(Text, Text)]
getArgstr Options
opts)
    NValue t f m
f <- Maybe Path -> NExprLoc -> m (NValue t f m)
evaluator Maybe Path
mpath NExprLoc
expr
    NValue t f m
f' <- forall v (m :: * -> *). MonadValue v m => v -> m v
demand NValue t f m
f
    NValue t f m
val <-
      case NValue t f m
f' of
        NVClosure Params ()
_ NValue t f m -> m (NValue t f m)
g -> NValue t f m -> m (NValue t f m)
g forall a b. (a -> b) -> a -> b
$ forall {w :: * -> *} {t} {m :: * -> *} {a}.
(Comonad w, Applicative w) =>
PositionSet
-> AttrSet (Free (NValue' t w m) a) -> Free (NValue' t w m) a
NVSet forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$ forall k v. (Eq k, Hashable k) => [(k, v)] -> HashMap k v
M.fromList [(VarName, NValue t f m)]
args
        NValue t f m
_             -> forall (f :: * -> *) a. Applicative f => a -> f a
pure NValue t f m
f
    forall e t (f :: * -> *) (m :: * -> *) a.
(MonadNix e t f m, Has e Options) =>
(NValue t f m -> m a) -> NValue t f m -> m a
processResult NValue t f m -> m a
handler NValue t f m
val
 where
  parseArg :: Text -> NExpr
parseArg Text
s =
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
      (forall a. [Char] -> a
errorWithoutStackTrace forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall b a. (Show a, IsString b) => a -> b
show)
      forall a. a -> a
id
      (Text -> Result NExpr
parseNixText Text
s)

  eval' :: NExpr -> m (NValue t f m)
eval' = forall e (m :: * -> *) t (f :: * -> *).
(Framed e m, MonadThunk t m (NValue t f m),
 MonadDataErrorContext t f m, HasCitations m (NValue t f m) t,
 HasCitations1 m (NValue t f m) f, Ord (ThunkId m)) =>
NValue t f m -> m (NValue t f m)
normalForm forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall e t (f :: * -> *) (m :: * -> *).
(MonadNix e t f m, Has e Options) =>
Maybe Path -> NExpr -> m (NValue t f m)
nixEvalExpr Maybe Path
mpath

processResult
  :: forall e t f m a
   . (MonadNix e t f m, Has e Options)
  => (NValue t f m -> m a)
  -> NValue t f m
  -> m a
processResult :: forall e t (f :: * -> *) (m :: * -> *) a.
(MonadNix e t f m, Has e Options) =>
(NValue t f m -> m a) -> NValue t f m -> m a
processResult NValue t f m -> m a
h NValue t f m
val =
  do
    Options
opts <- forall e (m :: * -> *).
(MonadReader e m, Has e Options) =>
m Options
askOptions
    forall b a. b -> (a -> b) -> Maybe a -> b
maybe
      (NValue t f m -> m a
h NValue t f m
val)
      (\ (coerce :: forall a b. Coercible a b => a -> b
coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> [Text]
Text.splitOn Text
"." -> [VarName]
keys) -> [VarName] -> NValue t f m -> m a
processKeys [VarName]
keys NValue t f m
val)
      (Options -> Maybe Text
getAttr Options
opts)
 where
  processKeys :: [VarName] -> NValue t f m -> m a
  processKeys :: [VarName] -> NValue t f m -> m a
processKeys [VarName]
kys NValue t f m
v =
    forall (t :: * -> *) b a. Foldable t => b -> (t a -> b) -> t a -> b
handlePresence
      (NValue t f m -> m a
h NValue t f m
v)
      (\ ((VarName
k : [VarName]
ks) :: [VarName]) ->
        do
          NValue t f m
v' <- forall v (m :: * -> *). MonadValue v m => v -> m v
demand NValue t f m
v
          case (VarName
k, NValue t f m
v') of
            (forall a. Integral a => Reader a
Text.decimal forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce -> Right (Int
n,Text
""), NVList [NValue t f m]
xs) -> [VarName] -> NValue t f m -> m a
processKeys [VarName]
ks forall a b. (a -> b) -> a -> b
$ [NValue t f m]
xs forall a. [a] -> Int -> a
!! Int
n
            (VarName
_,         NVSet PositionSet
_ AttrSet (NValue t f m)
xs) ->
              forall b a. b -> (a -> b) -> Maybe a -> b
maybe
                (forall a. [Char] -> a
errorWithoutStackTrace forall a b. (a -> b) -> a -> b
$ [Char]
"Set does not contain key ''" forall a. Semigroup a => a -> a -> a
<> forall b a. (Show a, IsString b) => a -> b
show VarName
k forall a. Semigroup a => a -> a -> a
<> [Char]
"''.")
                ([VarName] -> NValue t f m -> m a
processKeys [VarName]
ks)
                (forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
M.lookup VarName
k AttrSet (NValue t f m)
xs)
            (VarName
_, NValue t f m
_) -> forall a. [Char] -> a
errorWithoutStackTrace forall a b. (a -> b) -> a -> b
$ [Char]
"Expected a set or list for selector '" forall a. Semigroup a => a -> a -> a
<> forall b a. (Show a, IsString b) => a -> b
show VarName
k forall a. Semigroup a => a -> a -> a
<> [Char]
"', but got: " forall a. Semigroup a => a -> a -> a
<> forall b a. (Show a, IsString b) => a -> b
show NValue t f m
v
      )
      [VarName]
kys