-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathNix.hs
159 lines (151 loc) · 4.47 KB
/
Nix.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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 transform alg mpath = withNixContext mpath . adi transform 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 = nixEval id 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 =
nixEval
Eval.addMetaInfo
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 mpath = withNixContext mpath . 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 mpath evaluator handler expr =
do
opts <- askOptions
(coerce -> args) <-
(traverse . traverse)
eval'
$ (second parseArg <$> getArg opts)
<> (second mkStr <$> getArgstr opts)
f <- evaluator mpath expr
f' <- demand f
val <-
case f' of
NVClosure _ g -> g $ NVSet mempty $ M.fromList args
_ -> pure f
processResult handler val
where
parseArg s =
either
(errorWithoutStackTrace . show)
id
(parseNixText s)
eval' = normalForm <=< nixEvalExpr 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 h val =
do
opts <- askOptions
maybe
(h val)
(\ (coerce . Text.splitOn "." -> keys) -> processKeys keys val)
(getAttr opts)
where
processKeys :: [VarName] -> NValue t f m -> m a
processKeys kys v =
handlePresence
(h v)
(\ ((k : ks) :: [VarName]) ->
do
v' <- demand v
case (k, v') of
(Text.decimal . coerce -> Right (n,""), NVList xs) -> processKeys ks $ xs !! n
(_, NVSet _ xs) ->
maybe
(errorWithoutStackTrace $ "Set does not contain key ''" <> show k <> "''.")
(processKeys ks)
(M.lookup k xs)
(_, _) -> errorWithoutStackTrace $ "Expected a set or list for selector '" <> show k <> "', but got: " <> show v
)
kys