Nix 2.26.3
Nix, the purely functional package manager; unstable internal interfaces
 
Loading...
Searching...
No Matches
value.hh
Go to the documentation of this file.
1#pragma once
3
4#include <cassert>
5#include <span>
6
7#include "eval-gc.hh"
8#include "symbol-table.hh"
9#include "value/context.hh"
10#include "source-path.hh"
11#include "print-options.hh"
12#include "checked-arithmetic.hh"
13
14#include <nlohmann/json_fwd.hpp>
15
16namespace nix {
17
18struct Value;
19class BindingsBuilder;
20
21
22typedef enum {
23 tUninitialized = 0,
24 tInt = 1,
25 tBool,
26 tString,
27 tPath,
28 tNull,
29 tAttrs,
30 tList1,
31 tList2,
32 tListN,
33 tThunk,
34 tApp,
35 tLambda,
36 tPrimOp,
37 tPrimOpApp,
38 tExternal,
39 tFloat
40} InternalType;
41
47typedef enum {
48 nThunk,
49 nInt,
50 nFloat,
51 nBool,
52 nString,
53 nPath,
54 nNull,
55 nAttrs,
56 nList,
57 nFunction,
58 nExternal
59} ValueType;
60
61class Bindings;
62struct Env;
63struct Expr;
64struct ExprLambda;
65struct ExprBlackHole;
66struct PrimOp;
67class Symbol;
68class PosIdx;
69struct Pos;
70class StorePath;
71class EvalState;
72class XMLWriter;
73class Printer;
74
75using NixInt = checked::Checked<int64_t>;
76using NixFloat = double;
77
83{
84 friend std::ostream & operator << (std::ostream & str, const ExternalValueBase & v);
85 friend class Printer;
86 protected:
90 virtual std::ostream & print(std::ostream & str) const = 0;
91
92 public:
96 virtual std::string showType() const = 0;
97
101 virtual std::string typeOf() const = 0;
102
107 virtual std::string coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const;
108
113 virtual bool operator ==(const ExternalValueBase & b) const noexcept;
114
118 virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict,
119 NixStringContext & context, bool copyToStore = true) const;
120
124 virtual void printValueAsXML(EvalState & state, bool strict, bool location,
125 XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
126 const PosIdx pos) const;
127
128 virtual ~ExternalValueBase()
129 {
130 };
131};
132
133std::ostream & operator << (std::ostream & str, const ExternalValueBase & v);
134
135
136class ListBuilder
137{
138 const size_t size;
139 Value * inlineElems[2] = {nullptr, nullptr};
140public:
141 Value * * elems;
142 ListBuilder(EvalState & state, size_t size);
143
144 // NOTE: Can be noexcept because we are just copying integral values and
145 // raw pointers.
146 ListBuilder(ListBuilder && x) noexcept
147 : size(x.size)
148 , inlineElems{x.inlineElems[0], x.inlineElems[1]}
149 , elems(size <= 2 ? inlineElems : x.elems)
150 { }
151
152 Value * & operator [](size_t n)
153 {
154 return elems[n];
155 }
156
157 typedef Value * * iterator;
158
159 iterator begin() { return &elems[0]; }
160 iterator end() { return &elems[size]; }
161
162 friend struct Value;
163};
164
165
166struct Value
167{
168private:
169 InternalType internalType = tUninitialized;
170
171 friend std::string showType(const Value & v);
172
173public:
174
175 void print(EvalState &state, std::ostream &str, PrintOptions options = PrintOptions {});
176
177 // Functions needed to distinguish the type
178 // These should be removed eventually, by putting the functionality that's
179 // needed by callers into methods of this type
180
181 // type() == nThunk
182 inline bool isThunk() const { return internalType == tThunk; };
183 inline bool isApp() const { return internalType == tApp; };
184 inline bool isBlackhole() const;
185
186 // type() == nFunction
187 inline bool isLambda() const { return internalType == tLambda; };
188 inline bool isPrimOp() const { return internalType == tPrimOp; };
189 inline bool isPrimOpApp() const { return internalType == tPrimOpApp; };
190
214 const char * c_str;
215 const char * * context; // must be in sorted order
216 };
217
218 struct Path {
219 SourceAccessor * accessor;
220 const char * path;
221 };
222
224 Env * env;
225 Expr * expr;
226 };
227
229 Value * left, * right;
230 };
231
232 struct Lambda {
233 Env * env;
234 ExprLambda * fun;
235 };
236
237 using Payload = union
238 {
239 NixInt integer;
240 bool boolean;
241
242 StringWithContext string;
243
244 Path path;
245
246 Bindings * attrs;
247 struct {
248 size_t size;
249 Value * const * elems;
250 } bigList;
251 Value * smallList[2];
252 ClosureThunk thunk;
253 FunctionApplicationThunk app;
254 Lambda lambda;
255 PrimOp * primOp;
256 FunctionApplicationThunk primOpApp;
257 ExternalValueBase * external;
258 NixFloat fpoint;
259 };
260
261 Payload payload;
262
270 inline ValueType type(bool invalidIsThunk = false) const
271 {
272 switch (internalType) {
273 case tUninitialized: break;
274 case tInt: return nInt;
275 case tBool: return nBool;
276 case tString: return nString;
277 case tPath: return nPath;
278 case tNull: return nNull;
279 case tAttrs: return nAttrs;
280 case tList1: case tList2: case tListN: return nList;
281 case tLambda: case tPrimOp: case tPrimOpApp: return nFunction;
282 case tExternal: return nExternal;
283 case tFloat: return nFloat;
284 case tThunk: case tApp: return nThunk;
285 }
286 if (invalidIsThunk)
287 return nThunk;
288 else
289 unreachable();
290 }
291
292 inline void finishValue(InternalType newType, Payload newPayload)
293 {
294 payload = newPayload;
295 internalType = newType;
296 }
297
303 inline bool isValid() const
304 {
305 return internalType != tUninitialized;
306 }
307
308 inline void mkInt(NixInt::Inner n)
309 {
310 mkInt(NixInt{n});
311 }
312
313 inline void mkInt(NixInt n)
314 {
315 finishValue(tInt, { .integer = n });
316 }
317
318 inline void mkBool(bool b)
319 {
320 finishValue(tBool, { .boolean = b });
321 }
322
323 inline void mkString(const char * s, const char * * context = 0)
324 {
325 finishValue(tString, { .string = { .c_str = s, .context = context } });
326 }
327
328 void mkString(std::string_view s);
329
330 void mkString(std::string_view s, const NixStringContext & context);
331
332 void mkStringMove(const char * s, const NixStringContext & context);
333
334 inline void mkString(const SymbolStr & s)
335 {
336 mkString(s.c_str());
337 }
338
339 void mkPath(const SourcePath & path);
340 void mkPath(std::string_view path);
341
342 inline void mkPath(SourceAccessor * accessor, const char * path)
343 {
344 finishValue(tPath, { .path = { .accessor = accessor, .path = path } });
345 }
346
347 inline void mkNull()
348 {
349 finishValue(tNull, {});
350 }
351
352 inline void mkAttrs(Bindings * a)
353 {
354 finishValue(tAttrs, { .attrs = a });
355 }
356
357 Value & mkAttrs(BindingsBuilder & bindings);
358
359 void mkList(const ListBuilder & builder)
360 {
361 if (builder.size == 1)
362 finishValue(tList1, { .smallList = { builder.inlineElems[0] } });
363 else if (builder.size == 2)
364 finishValue(tList2, { .smallList = { builder.inlineElems[0], builder.inlineElems[1] } });
365 else
366 finishValue(tListN, { .bigList = { .size = builder.size, .elems = builder.elems } });
367 }
368
369 inline void mkThunk(Env * e, Expr * ex)
370 {
371 finishValue(tThunk, { .thunk = { .env = e, .expr = ex } });
372 }
373
374 inline void mkApp(Value * l, Value * r)
375 {
376 finishValue(tApp, { .app = { .left = l, .right = r } });
377 }
378
379 inline void mkLambda(Env * e, ExprLambda * f)
380 {
381 finishValue(tLambda, { .lambda = { .env = e, .fun = f } });
382 }
383
384 inline void mkBlackhole();
385
386 void mkPrimOp(PrimOp * p);
387
388 inline void mkPrimOpApp(Value * l, Value * r)
389 {
390 finishValue(tPrimOpApp, { .primOpApp = { .left = l, .right = r } });
391 }
392
396 const PrimOp * primOpAppPrimOp() const;
397
398 inline void mkExternal(ExternalValueBase * e)
399 {
400 finishValue(tExternal, { .external = e });
401 }
402
403 inline void mkFloat(NixFloat n)
404 {
405 finishValue(tFloat, { .fpoint = n });
406 }
407
408 bool isList() const
409 {
410 return internalType == tList1 || internalType == tList2 || internalType == tListN;
411 }
412
413 Value * const * listElems()
414 {
415 return internalType == tList1 || internalType == tList2 ? payload.smallList : payload.bigList.elems;
416 }
417
418 std::span<Value * const> listItems() const
419 {
420 assert(isList());
421 return std::span<Value * const>(listElems(), listSize());
422 }
423
424 Value * const * listElems() const
425 {
426 return internalType == tList1 || internalType == tList2 ? payload.smallList : payload.bigList.elems;
427 }
428
429 size_t listSize() const
430 {
431 return internalType == tList1 ? 1 : internalType == tList2 ? 2 : payload.bigList.size;
432 }
433
434 PosIdx determinePos(const PosIdx pos) const;
435
441 bool isTrivial() const;
442
443 SourcePath path() const
444 {
445 assert(internalType == tPath);
446 return SourcePath(
447 ref(payload.path.accessor->shared_from_this()),
448 CanonPath(CanonPath::unchecked_t(), payload.path.path));
449 }
450
451 std::string_view string_view() const
452 {
453 assert(internalType == tString);
454 return std::string_view(payload.string.c_str);
455 }
456
457 const char * c_str() const
458 {
459 assert(internalType == tString);
460 return payload.string.c_str;
461 }
462
463 const char * * context() const
464 {
465 return payload.string.context;
466 }
467
468 ExternalValueBase * external() const
469 { return payload.external; }
470
471 const Bindings * attrs() const
472 { return payload.attrs; }
473
474 const PrimOp * primOp() const
475 { return payload.primOp; }
476
477 bool boolean() const
478 { return payload.boolean; }
479
480 NixInt integer() const
481 { return payload.integer; }
482
483 NixFloat fpoint() const
484 { return payload.fpoint; }
485};
486
487
488extern ExprBlackHole eBlackHole;
489
490bool Value::isBlackhole() const
491{
492 return internalType == tThunk && payload.thunk.expr == (Expr*) &eBlackHole;
493}
494
495void Value::mkBlackhole()
496{
497 mkThunk(nullptr, (Expr *) &eBlackHole);
498}
499
500
501typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector;
502typedef std::unordered_map<Symbol, Value *, std::hash<Symbol>, std::equal_to<Symbol>, traceable_allocator<std::pair<const Symbol, Value *>>> ValueMap;
503typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>> ValueVectorMap;
504
505
509typedef std::shared_ptr<Value *> RootValue;
510
511RootValue allocRootValue(Value * v);
512
513void forceNoNullByte(std::string_view s, std::function<Pos()> = nullptr);
514
515}
Definition attr-set.hh:136
Definition attr-set.hh:48
Definition eval.hh:182
Definition value.hh:83
virtual nlohmann::json printValueAsJSON(EvalState &state, bool strict, NixStringContext &context, bool copyToStore=true) const
Definition value-to-json.cc:118
virtual std::string showType() const =0
virtual bool operator==(const ExternalValueBase &b) const noexcept
Definition eval.cc:3180
virtual std::string typeOf() const =0
virtual std::ostream & print(std::ostream &str) const =0
virtual std::string coerceToString(EvalState &state, const PosIdx &pos, NixStringContext &context, bool copyMore, bool copyToStore) const
Definition eval.cc:3172
virtual void printValueAsXML(EvalState &state, bool strict, bool location, XMLWriter &doc, NixStringContext &context, PathSet &drvsSeen, const PosIdx pos) const
Definition value-to-xml.cc:159
Definition pos-idx.hh:9
Definition xml-writer.hh:17
friend class EvalState
Definition lexer.l:5728
boost::format f(fs)
return s
Definition lexer.l:459
std::ostream & str
Definition lexer.l:1728
ref< SourceAccessor > accessor
Definition lexer.l:4655
T x
Definition lexer.l:2648
std::shared_ptr< T > p
Definition lexer.l:1269
const char * doc
Definition lexer.l:7055
CanonPath(std::string_view raw)
Bindings * bindings
Definition lexer.l:6423
Options for printing Nix values.
SourcePath.
Definition eval.hh:152
Definition nixexpr.hh:467
Definition nixexpr.hh:332
Definition nixexpr.hh:81
Definition position.hh:20
Definition eval.hh:68
Definition print-options.hh:39
Definition source-accessor.hh:42
Definition value.hh:223
Definition value.hh:232
Definition value.hh:218
Definition value.hh:213
Definition value.hh:167
bool isValid() const
Definition value.hh:303
const PrimOp * primOpAppPrimOp() const
Definition eval.cc:481
ValueType type(bool invalidIsThunk=false) const
Definition value.hh:270
bool isTrivial() const
Definition eval.cc:158
ValueType
Definition value.hh:47
std::shared_ptr< Value * > RootValue
Definition value.hh:509