Nix  2.93.0-dev
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
eval.hh
Go to the documentation of this file.
1#pragma once
3
6#include "lix/libexpr/gc-alloc.hh"
11#include "lix/libutil/types.hh"
12#include "lix/libexpr/value.hh"
15#include "lix/libutil/config.hh"
19#include "lix/libutil/backed-string-view.hh"
20
21#include <map>
22#include <optional>
23#include <unordered_map>
24#include <functional>
25
26namespace nix {
27
28class Store;
29class EvalState;
30class StorePath;
31struct SingleDerivedPath;
32enum RepairFlag : bool;
33struct MemoryInputAccessor;
34namespace eval_cache {
35 class EvalCache;
36}
37
41using PrimOpImpl = void(EvalState & state, PosIdx pos, Value ** args, Value & v);
42
46struct PrimOp
47{
51 std::string name;
52
57 std::vector<std::string> args;
58
65 size_t arity = 0;
66
70 const char * doc = nullptr;
71
77 bool isCompactTrace = false;
78
82 std::function<PrimOpImpl> fun;
83
87 std::optional<ExperimentalFeature> experimentalFeature;
88};
89
90std::ostream & operator<<(std::ostream & output, PrimOp & primOp);
91
96{
102 ValueType type = nThunk;
103
107 const char * doc = nullptr;
108
112 bool impureOnly = false;
113};
114
115using ValMap = GcMap<std::string, Value *>;
116
117struct Env
118{
119 Env * up;
120 Value * values[0];
121};
122
123void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env);
124void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env, int lvl = 0);
125
126std::unique_ptr<ValMap> mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env & env);
127
128void copyContext(const Value & v, NixStringContext & context);
129
130
131std::string printValue(EvalState & state, Value & v);
132std::ostream & operator << (std::ostream & os, const ValueType t);
133
134
138void initLibExpr();
139
140
141struct RegexCache;
142
144 std::shared_ptr<Pos> pos;
145 const Expr & expr;
146 const Env & env;
147 HintFmt hint;
148 bool isError;
149 std::shared_ptr<const DebugTrace> parent;
150};
151
153{
154private:
155 std::weak_ptr<const DebugTrace> latestTrace;
156 const PosTable & positions;
157 const SymbolTable & symbols;
158
159public:
160 std::function<ReplExitStatus(ValMap const & extraEnv, NeverAsync)> errorCallback;
161 bool stop = false;
162 bool inDebugger = false;
163 std::map<const Expr *, const std::shared_ptr<const StaticEnv>> exprEnvs;
164 int trylevel = 0;
165
166 explicit DebugState(
167 const PosTable & positions,
168 const SymbolTable & symbols,
169 std::function<ReplExitStatus(ValMap const & extraEnv, NeverAsync)> errorCallback
170 )
171 : positions(positions)
172 , symbols(symbols)
173 , errorCallback(errorCallback)
174 {
175 assert(errorCallback);
176 }
177
178 void onEvalError(const EvalError * error, const Env & env, const Expr & expr, NeverAsync = {});
179
180 const std::shared_ptr<const StaticEnv> staticEnvFor(const Expr & expr) const
181 {
182 if (auto i = exprEnvs.find(&expr); i != exprEnvs.end()) {
183 return i->second;
184 }
185 return nullptr;
186 }
187
189 {
190 friend struct DebugState;
191 template<class T>
192 friend class EvalErrorBuilder;
193
194 // holds both the data for this frame *and* a deleter that pulls this frame
195 // off the trace stack. EvalErrorBuilder uses this for withFrame fake trace
196 // frames, and to avoid needing to see this class definition in its header.
197 const std::shared_ptr<const DebugTrace> entry = nullptr;
198
199 explicit TraceFrame(std::shared_ptr<const DebugTrace> entry): entry(std::move(entry)) {}
200
201 public:
202 TraceFrame(std::nullptr_t) {}
203 };
204
205 TraceFrame addTrace(DebugTrace t);
206
210 {
211 for (auto current = latestTrace.lock(); current; current = current->parent) {
212 co_yield current.get();
213 }
214 }
215};
216
218{
219 const Symbol outPath, drvPath, type, meta, name, value, system, overrides, outputs, outputName,
220 ignoreNulls, file, line, column, functor, toString, right, wrong, structuredAttrs,
221 allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites, maxSize,
222 maxClosureSize, builder, args, contentAddressed, impure, outputHash, outputHashAlgo,
223 outputHashMode, recurseForDerivations, description, self, startSet, operator_, key,
224 path, prefix, outputSpecified;
225
226 const Expr::AstSymbols exprSymbols;
227
228 explicit StaticSymbols(SymbolTable & symbols);
229};
230
232{
236 std::shared_ptr<void *> valueAllocCache;
237
241 std::shared_ptr<void *> env1AllocCache;
242
243public:
245 {
246 unsigned long nrEnvs = 0;
247 unsigned long nrValuesInEnvs = 0;
248 unsigned long nrValues = 0;
249 unsigned long nrAttrsets = 0;
250 unsigned long nrAttrsInAttrsets = 0;
251 unsigned long nrListElems = 0;
252 };
253
254 EvalMemory();
255
256 EvalMemory(const EvalMemory &) = delete;
257 EvalMemory(EvalMemory &&) = delete;
258 EvalMemory & operator=(const EvalMemory &) = delete;
259 EvalMemory & operator=(EvalMemory &&) = delete;
260
261 inline Value * allocValue();
262 inline Env & allocEnv(size_t size);
263
264 Bindings * allocBindings(size_t capacity);
265 Value newList(size_t length);
266
267 BindingsBuilder buildBindings(SymbolTable & symbols, size_t capacity)
268 {
269 return BindingsBuilder(*this, symbols, allocBindings(capacity));
270 }
271
272 const Statistics getStats() const { return stats; }
273
274private:
275 Statistics stats;
276};
277
279{
280 EvalMemory & mem;
281 SymbolTable & symbols;
282
283public:
284 explicit EvalBuiltins(
285 EvalMemory & mem,
286 SymbolTable & symbols,
287 const SearchPath & searchPath,
288 const Path & storeDir,
289 size_t size = 128
290 );
291
297
301 std::shared_ptr<StaticEnv> staticEnv; // !!! should be private
302
309 std::vector<std::pair<std::string, Constant>> constantInfos;
310
311private:
312 unsigned int baseEnvDispl = 0;
313
314 void createBaseEnv(const SearchPath & searchPath, const Path & storeDir);
315
316 Value * addConstant(const std::string & name, const Value & v, Constant info);
317
318 void addConstant(const std::string & name, Value * v, Constant info);
319
320 Value * addPrimOp(PrimOp && primOp);
321
322 Value prepareNixPath(const SearchPath & searchPath);
323
324public:
325 Value & get(const std::string & name);
326
327 struct Doc
328 {
329 Pos pos;
330 std::optional<std::string> name;
331 size_t arity;
332 std::vector<std::string> args;
337 const char * doc;
338 };
339
340 std::optional<Doc> getDoc(Value & v);
341};
342
343struct CachedEvalFile;
344
346{
347 RootValue vCallFlake;
348 RootValue vImportedDrvToDerivation;
349
353 std::shared_ptr<RegexCache> regexes;
354
358 std::map<SourcePath, std::shared_ptr<CachedEvalFile>> fileEval;
359};
360
362{
363 const PosTable & positions;
364 DebugState * debug;
365
366 template<class T, typename... Args>
367 [[gnu::noinline]]
368 EvalErrorBuilder<T> make(const Args & ... args) {
369 return EvalErrorBuilder<T>(positions, debug, args...);
370 }
371};
372
374{
375 ref<Store> store;
376 SearchPath searchPath_;
377 EvalErrorContext & errors;
378
379public:
380 EvalPaths(
381 AsyncIoRoot & aio,
382 const ref<Store> & store,
383 SearchPath searchPath,
384 EvalErrorContext & errors
385 );
386
387 const SearchPath & searchPath() const { return searchPath_; }
388
389private:
390 struct AllowedPath
391 {
392 struct ComponentLess : std::less<>
393 {
394 // we'll only use this for string-likes, it's fine. trust me sis.
395 using is_transparent = void;
396 };
397
398 std::map<std::string, AllowedPath, ComponentLess> children;
399
400 bool allowAllChildren = false;
401 };
402
407 std::optional<AllowedPath> allowedPaths;
408
409
410 /* Cache for calls to addToStore(); maps source paths to the store
411 paths. */
412 std::map<SourcePath, StorePath> srcToStore;
413
414 std::map<std::string, std::optional<std::string>> searchPathResolved;
415
419 std::unordered_map<Path, CheckedSourcePath> resolvedPaths;
420
421public:
425 void allowPath(const Path & path);
426
431 void allowPath(const StorePath & storePath);
432
436 void allowAndSetStorePathString(const StorePath & storePath, Value & v);
437
443
448
449 void checkURI(const std::string & uri);
450
460 Path toRealPath(const Path & path, const NixStringContext & context);
461
468 template<typename T, typename E>
469 struct PathResult : private std::variant<T, EvalErrorBuilder<E>>
470 {
471 PathResult(T p) : std::variant<T, EvalErrorBuilder<E>>(std::move(p)) {}
472 PathResult(EvalErrorBuilder<E> e) : std::variant<T, EvalErrorBuilder<E>>(std::move(e)) {}
473
474 T unwrap(NeverAsync = {}) &&
475 {
476 return std::visit(
478 [](T & p) -> T { return std::move(p); },
479 [](EvalErrorBuilder<E> & e) -> T {
480 std::move(e).debugThrow(always_progresses);
481 }
482 },
483 static_cast<std::variant<T, EvalErrorBuilder<E>> &>(*this)
484 );
485 }
486 };
487
491 kj::Promise<Result<PathResult<SourcePath, ThrownError>>> findFile(const std::string_view path);
492 kj::Promise<Result<PathResult<SourcePath, ThrownError>>>
493 findFile(const SearchPath & searchPath, const std::string_view path, const PosIdx pos = noPos);
494
502 kj::Promise<Result<std::optional<std::string>>>
504
505 kj::Promise<Result<PathResult<StorePath, EvalError>>> copyPathToStore(
506 NixStringContext & context, const SourcePath & path, RepairFlag repair = NoRepair
507 );
508
515 void mkStorePathString(const StorePath & storePath, Value & v);
516};
517
519{
520 unsigned long nrLookups = 0;
521 unsigned long nrAvoided = 0;
522 unsigned long nrOpUpdates = 0;
523 unsigned long nrOpUpdateValuesCopied = 0;
524 unsigned long nrListConcats = 0;
525 unsigned long nrPrimOpCalls = 0;
526 unsigned long nrFunctionCalls = 0;
527 unsigned long nrThunks = 0;
528
529 bool countCalls = false;
530
531 std::map<std::string, size_t> primOpCalls;
532 std::map<ExprLambda *, size_t> functionCalls;
533 std::map<PosIdx, size_t> attrSelects;
534
535 void addCall(ExprLambda & fun);
536};
537
539{
540 friend class EvalBuiltins;
541 friend class EvalState;
542
543 EvalState * activeEval = nullptr;
544
545public:
546 SymbolTable symbols;
547 PosTable positions;
548 const StaticSymbols s;
549 EvalMemory mem;
550 EvalRuntimeCaches caches;
551 EvalPaths paths;
552 EvalBuiltins builtins;
553 EvalStatistics stats;
554
559 RepairFlag repair;
560
565
570
571 std::unique_ptr<DebugState> debug;
572 EvalErrorContext errors;
573
574 Evaluator(
575 AsyncIoRoot & aio,
576 const SearchPath & _searchPath,
578 std::shared_ptr<Store> buildStore = nullptr,
579 std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl = nullptr
580 );
581
582 Evaluator(const Evaluator &) = delete;
583 Evaluator(Evaluator &&) = delete;
584 Evaluator & operator=(const Evaluator &) = delete;
585 Evaluator & operator=(Evaluator &&) = delete;
586
591 Expr & parseExprFromFile(const CheckedSourcePath & path, std::shared_ptr<StaticEnv> & staticEnv);
592
597 std::string s,
598 const SourcePath & basePath,
599 std::shared_ptr<StaticEnv> & staticEnv,
600 const FeatureSettings & xpSettings = featureSettings
601 );
603 std::string s,
604 const SourcePath & basePath,
605 const FeatureSettings & xpSettings = featureSettings
606 );
607
608 Expr & parseStdin();
609
613 void evalLazily(Expr & e, Value & v);
614
615private:
616 Expr * parse(
617 char * text,
618 size_t length,
619 Pos::Origin origin,
620 const SourcePath & basePath,
621 std::shared_ptr<StaticEnv> & staticEnv,
622 const FeatureSettings & xpSettings = featureSettings);
623
624public:
625 BindingsBuilder buildBindings(size_t capacity)
626 {
627 return mem.buildBindings(symbols, capacity);
628 }
629
636 void maybePrintStats();
637
641 void printStatistics();
642
649 bool fullGC();
650
669};
670
671
673{
674 friend class Evaluator;
675
676 explicit EvalState(AsyncIoRoot & aio, Evaluator & ctx);
677
678public:
679 Evaluator & ctx;
680 AsyncIoRoot & aio;
681
682 EvalState(const EvalState &) = delete;
683 EvalState(EvalState &&) = delete;
684 EvalState & operator=(const EvalState &) = delete;
685 EvalState & operator=(EvalState &&) = delete;
686
687 ~EvalState();
688
692 void evalFile(const SourcePath & path, Value & v);
693
694 void resetFileCache();
695
701 void eval(Expr & e, Value & v);
702
707 inline bool evalBool(Env & env, Expr & e);
708 inline bool evalBool(Env & env, Expr & e, const PosIdx pos, std::string_view errorCtx);
709 inline void evalAttrs(Env & env, Expr & e, Value & v, const PosIdx pos, std::string_view errorCtx);
710
717 inline void forceValue(Value & v, const PosIdx pos);
718
719 void tryFixupBlackHolePos(Value & v, PosIdx pos);
720
725 void forceValueDeep(Value & v);
726
730 NixInt forceInt(Value & v, const PosIdx pos, std::string_view errorCtx);
731 NixFloat forceFloat(Value & v, const PosIdx pos, std::string_view errorCtx);
732 bool forceBool(Value & v, const PosIdx pos, std::string_view errorCtx);
733
734 void forceAttrs(Value & v, const PosIdx pos, std::string_view errorCtx);
735 inline void forceList(Value & v, const PosIdx pos, std::string_view errorCtx);
739 void forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx);
740 std::string_view forceString(Value & v, const PosIdx pos, std::string_view errorCtx);
741 std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx);
742 std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
743
748 [[nodiscard]] StringMap realiseContext(const NixStringContext & context);
749
750public:
755 bool isDerivation(Value & v);
756
757 std::optional<std::string> tryAttrsToString(const PosIdx pos, Value & v,
758 NixStringContext & context, bool coerceMore = false, bool copyToStore = true);
759
768 BackedStringView coerceToString(const PosIdx pos, Value & v, NixStringContext & context,
769 std::string_view errorCtx,
770 bool coerceMore = false, bool copyToStore = true,
771 bool canonicalizePath = true);
772
780 SourcePath coerceToPath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx);
781
785 StorePath coerceToStorePath(const PosIdx pos, Value & v, NixStringContext & context, std::string_view errorCtx);
786
790 std::pair<SingleDerivedPath, std::string_view> coerceToSingleDerivedPathUnchecked(const PosIdx pos, Value & v, std::string_view errorCtx);
791
807 SingleDerivedPath coerceToSingleDerivedPath(const PosIdx pos, Value & v, std::string_view errorCtx);
808
809private:
810
811 inline Value * lookupVar(Env * env, const ExprVar & var, bool noEval);
812
813 friend struct ExprVar;
814 friend struct ExprSet;
815 friend struct ExprLet;
816
820 size_t callDepth = 0;
821
822public:
823
828 bool eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_view errorCtx);
829
830 bool isFunctor(Value & fun);
831
832 // FIXME: use std::span
833 void callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos);
834
835 void callFunction(Value & fun, Value & arg, Value & vRes, const PosIdx pos)
836 {
837 Value * args[] = {&arg};
838 callFunction(fun, 1, args, vRes, pos);
839 }
840
845 void autoCallFunction(Bindings & args, Value & fun, Value & res);
846
847 void mkPos(Value & v, PosIdx pos);
848
869 void mkOutputString(
870 Value & value,
871 const SingleDerivedPath::Built & b,
872 std::optional<StorePath> optStaticOutputPath,
873 const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
874
881 const SingleDerivedPath & p,
882 Value & v);
883
884 void concatLists(Value & v, size_t nrLists, Value * * lists, const PosIdx pos, std::string_view errorCtx);
885
886private:
887
892 std::string mkOutputStringRaw(
893 const SingleDerivedPath::Built & b,
894 std::optional<StorePath> optStaticOutputPath,
895 const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
896
901 std::string mkSingleDerivedPathStringRaw(
902 const SingleDerivedPath & p);
903};
904
911std::string_view showType(ValueType type, bool withArticle = true);
912std::string showType(const Value & v);
913
914static constexpr std::string_view corepkgsPrefix{"/__corepkgs__/"};
915
916
917}
918
919#include "lix/libexpr/eval-inline.hh" // IWYU pragma: keep
Definition backed-string-view.hh:17
Definition args.hh:31
Definition attr-set.hh:129
Definition attr-set.hh:49
Definition source-path.hh:89
Definition eval.hh:189
Definition eval.hh:279
Env & env
Definition eval.hh:296
std::vector< std::pair< std::string, Constant > > constantInfos
Definition eval.hh:309
std::shared_ptr< StaticEnv > staticEnv
Definition eval.hh:301
Definition eval-error.hh:59
Definition eval-error.hh:23
Definition eval.hh:232
Definition eval.hh:374
void allowPath(const Path &path)
Definition eval.cc:374
kj::Promise< Result< std::optional< std::string > > > resolveSearchPathPath(const SearchPath::Path &path)
Definition eval.cc:2840
void allowAndSetStorePathString(const StorePath &storePath, Value &v)
Definition eval.cc:395
CheckedSourcePath checkSourcePath(const SourcePath &path)
Definition eval.cc:402
CheckedSourcePath resolveExprPath(SourcePath path)
Definition eval.cc:2731
Path toRealPath(const Path &path, const NixStringContext &context)
Definition eval.cc:521
void mkStorePathString(const StorePath &storePath, Value &v)
Definition eval.cc:883
kj::Promise< Result< PathResult< SourcePath, ThrownError > > > findFile(const std::string_view path)
Definition eval.cc:2802
Definition eval.hh:673
StringMap realiseContext(const NixStringContext &context)
Definition primops.cc:47
SourcePath coerceToPath(const PosIdx pos, Value &v, NixStringContext &context, std::string_view errorCtx)
Definition eval.cc:2431
StorePath coerceToStorePath(const PosIdx pos, Value &v, NixStringContext &context, std::string_view errorCtx)
Definition eval.cc:2440
void forceValueDeep(Value &v)
Definition eval.cc:2116
NixInt forceInt(Value &v, const PosIdx pos, std::string_view errorCtx)
Definition eval.cc:2153
void forceValue(Value &v, const PosIdx pos)
Definition eval-inline.hh:69
void mkOutputString(Value &value, const SingleDerivedPath::Built &b, std::optional< StorePath > optStaticOutputPath, const ExperimentalFeatureSettings &xpSettings=experimentalFeatureSettings)
Definition eval.cc:908
std::pair< SingleDerivedPath, std::string_view > coerceToSingleDerivedPathUnchecked(const PosIdx pos, Value &v, std::string_view errorCtx)
Definition eval.cc:2449
void evalFile(const SourcePath &path, Value &v)
Definition eval.cc:994
bool eqValues(Value &v1, Value &v2, const PosIdx pos, std::string_view errorCtx)
Definition eval.cc:2506
BackedStringView coerceToString(const PosIdx pos, Value &v, NixStringContext &context, std::string_view errorCtx, bool coerceMore=false, bool copyToStore=true, bool canonicalizePath=true)
Definition eval.cc:2306
SingleDerivedPath coerceToSingleDerivedPath(const PosIdx pos, Value &v, std::string_view errorCtx)
Definition eval.cc:2479
void mkSingleDerivedPathString(const SingleDerivedPath &p, Value &v)
Definition eval.cc:946
bool isDerivation(Value &v)
Definition eval.cc:2280
void eval(Expr &e, Value &v)
Definition eval.cc:1040
void autoCallFunction(Bindings &args, Value &fun, Value &res)
Definition eval.cc:1789
void forceFunction(Value &v, const PosIdx pos, std::string_view errorCtx)
Definition eval.cc:2219
bool evalBool(Env &env, Expr &e)
Definition eval.hh:539
void printStatistics()
Definition eval.cc:2613
void evalLazily(Expr &e, Value &v)
Definition eval.cc:863
box_ptr< EvalState > begin(AsyncIoRoot &aio)
Definition eval.cc:355
Expr & parseExprFromString(std::string s, const SourcePath &basePath, std::shared_ptr< StaticEnv > &staticEnv, const FeatureSettings &xpSettings=featureSettings)
Definition eval.cc:2769
const ref< Store > store
Definition eval.hh:564
RepairFlag repair
Definition eval.hh:559
bool fullGC()
Definition eval.cc:2584
Expr & parseExprFromFile(const CheckedSourcePath &path)
Definition eval.cc:2756
ref< Store > buildStore
Definition eval.hh:569
void maybePrintStats()
Definition eval.cc:2598
Definition fmt.hh:157
Definition pos-idx.hh:9
Definition pos-table.hh:16
Definition path.hh:21
Definition symbol-table.hh:75
Definition symbol-table.hh:52
Definition box_ptr.hh:16
Definition ref.hh:17
void(EvalState &state, PosIdx pos, Value **args, Value &v) PrimOpImpl
Definition eval.hh:41
ReplExitStatus
Definition repl-exit-status.hh:9
SourcePath.
Definition async.hh:36
Definition eval.cc:989
Definition eval.hh:96
const char * doc
Definition eval.hh:107
bool impureOnly
Definition eval.hh:112
ValueType type
Definition eval.hh:102
Definition eval.hh:153
Generator< const DebugTrace * > traces()
Definition eval.hh:209
Definition eval.hh:143
Definition eval.hh:118
Definition eval.hh:328
const char * doc
Definition eval.hh:337
Definition eval.hh:362
Definition eval.hh:245
Definition eval.hh:470
Definition eval.hh:346
std::shared_ptr< RegexCache > regexes
Definition eval.hh:353
std::map< SourcePath, std::shared_ptr< CachedEvalFile > > fileEval
Definition eval.hh:358
Definition eval.hh:519
Definition nixexpr.hh:333
Definition nixexpr.hh:385
Definition nixexpr.hh:246
Definition nixexpr.hh:108
Definition nixexpr.hh:54
Definition nixexpr.hh:47
Definition config.hh:382
Definition generator.hh:236
Definition types.hh:166
Definition position.hh:19
Definition eval.hh:47
std::vector< std::string > args
Definition eval.hh:57
bool isCompactTrace
Definition eval.hh:77
std::function< PrimOpImpl > fun
Definition eval.hh:82
std::optional< ExperimentalFeature > experimentalFeature
Definition eval.hh:87
std::string name
Definition eval.hh:51
size_t arity
Definition eval.hh:65
const char * doc
Definition eval.hh:70
Definition primops.cc:2567
Definition search-path.hh:83
Definition search-path.hh:16
Definition derived-path.hh:101
Definition source-path.hh:23
Definition nixexpr.hh:478
Definition eval.hh:218
Definition value.hh:191
Definition types.hh:158
std::string Path
Definition types.hh:28
constexpr NeverAsync always_progresses
Definition types.hh:175
ValueType
Definition value.hh:49
std::shared_ptr< Value * > RootValue
Definition value.hh:851