10#include "lix/libexpr/gc-alloc.hh"
16#include "lix/libutil/checked-arithmetic.hh"
17#include "lix/libutil/concepts.hh"
18#include "lix/libutil/json-fwd.hh"
78using NixInt = checked::Checked<int64_t>;
79using NixFloat = double;
87 friend std::ostream & operator << (std::ostream & str,
const ExternalValueBase & v);
93 virtual std::ostream &
print(std::ostream & str)
const = 0;
110 virtual std::string
coerceToString(
EvalState & state,
const PosIdx & pos, NixStringContext & context,
bool copyMore,
bool copyToStore)
const;
122 NixStringContext & context,
bool copyToStore =
true)
const;
128 XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
136std::ostream & operator << (std::ostream & str,
const ExternalValueBase & v);
140extern Expr *eBlackHoleAddr;
157 constexpr static path_t path{};
160 constexpr static list_t list{};
163 constexpr static attrs_t attrs{};
166 constexpr static thunk_t thunk{};
169 constexpr static null_t null{};
172 constexpr static app_t app{};
193 InternalType internalType;
195 friend std::string showType(
const Value & v);
206#define USING_VALUETYPE(name) using name = NewValueAs::name
207 USING_VALUETYPE(integer_t);
208 USING_VALUETYPE(floating_t);
209 USING_VALUETYPE(boolean_t);
210 USING_VALUETYPE(string_t);
211 USING_VALUETYPE(path_t);
212 USING_VALUETYPE(list_t);
213 USING_VALUETYPE(attrs_t);
214 USING_VALUETYPE(thunk_t);
215 USING_VALUETYPE(primop_t);
216 USING_VALUETYPE(app_t);
217 USING_VALUETYPE(null_t);
218 USING_VALUETYPE(primOpApp_t);
219 USING_VALUETYPE(lambda_t);
220 USING_VALUETYPE(external_t);
221 USING_VALUETYPE(blackhole_t);
222#undef USING_VALUETYPE
227 : internalType(static_cast<InternalType>(0))
247 : internalType(tFloat)
255 : internalType(tBool)
267 Value(string_t,
char const * strPtr,
char const ** contextPtr =
nullptr)
268 : internalType(tString)
269 , string({ .s = strPtr, .context = contextPtr })
277 Value(string_t, std::string_view copyFrom, NixStringContext
const & context = {})
278 : internalType(tString)
279 , string({ .s = gcCopyStringIfNeeded(copyFrom), .context =
nullptr })
281 if (context.empty()) {
287 this->
string.context = gcAllocType<char const *>(context.size() + 1);
290 for (NixStringContextElem
const & contextElem : context) {
291 this->
string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
296 this->
string.context[n] =
nullptr;
308 Value(string_t,
char const * strPtr, NixStringContext
const & context)
309 : internalType(tString)
310 , string({ .s = strPtr, .context =
nullptr })
312 if (context.empty()) {
318 this->
string.context = gcAllocType<char const *>(context.size() + 1);
321 for (NixStringContextElem
const & contextElem : context) {
322 this->
string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
327 this->
string.context[n] =
nullptr;
337 : internalType(tPath)
348 : internalType(tPath)
349 , _path(gcCopyStringIfNeeded(path.canonical().abs()))
365 Value(list_t, std::span<Value *> items)
367 if (items.size() == 1) {
368 this->internalType = tList1;
369 this->smallList[0] = items[0];
370 this->smallList[1] =
nullptr;
371 }
else if (items.size() == 2) {
372 this->internalType = tList2;
373 this->smallList[0] = items[0];
374 this->smallList[1] = items[1];
376 this->internalType = tListN;
377 this->bigList.size = items.size();
378 this->bigList.elems = items.data();
390 std::ranges::sized_range SizedIterableT,
393 Value(list_t, SizedIterableT & items, TransformerT
const & transformer)
395 if (items.size() == 1) {
396 this->internalType = tList1;
397 this->smallList[0] = transformer(*items.begin());
398 this->smallList[1] =
nullptr;
399 }
else if (items.size() == 2) {
400 this->internalType = tList2;
401 auto it = items.begin();
402 this->smallList[0] = transformer(*it);
404 this->smallList[1] = transformer(*it);
406 this->internalType = tListN;
407 this->bigList.size = items.size();
408 this->bigList.elems = gcAllocType<Value *>(items.size());
409 auto it = items.begin();
410 for (
size_t i = 0; i < items.size(); i++, it++) {
411 this->bigList.elems[i] = transformer(*it);
418 : internalType(tNull)
428 : internalType(tAttrs)
438 : internalType(tThunk)
439 , thunk({ .env = &env, .expr = &expr })
445 Value(primop_t, PrimOp & primop);
450 : internalType(tPrimOpApp)
451 , primOpApp({ .left = &lhs, .right = &rhs })
458 , app({ .left = &lhs, .right = &rhs })
464 : internalType(tExternal)
465 , external(&external)
476 : internalType(tLambda)
477 , lambda({ .env = &env, .fun = &lambda })
482 : internalType(tThunk)
483 , thunk({ .env =
nullptr, .expr = eBlackHoleAddr })
491 : internalType(rhs.internalType)
494 *
this = std::move(rhs);
497 Value & operator=(
Value const & rhs) =
default;
504 *
this =
static_cast<const Value &
>(rhs);
507 rhs.internalType =
static_cast<InternalType
>(0);
521 inline bool isThunk()
const {
return internalType == tThunk; };
522 inline bool isApp()
const {
return internalType == tApp; };
523 inline bool isBlackhole()
const
525 return internalType == tThunk && thunk.expr == eBlackHoleAddr;
529 inline bool isLambda()
const {
return internalType == tLambda; };
530 inline bool isPrimOp()
const {
return internalType == tPrimOp; };
531 inline bool isPrimOpApp()
const {
return internalType == tPrimOpApp; };
569 const char * * context;
578 uintptr_t _attrs_pad;
584 Value * smallList[2];
590 Value * left, * right;
598 uintptr_t _primop_pad;
601 Value * left, * right;
604 ExternalValueBase * external;
605 uintptr_t _external_pad;
609 uintptr_t _float_pad;
622 switch (internalType) {
623 case tInt:
return nInt;
624 case tBool:
return nBool;
625 case tString:
return nString;
626 case tPath:
return nPath;
627 case tNull:
return nNull;
628 case tAttrs:
return nAttrs;
629 case tList1:
case tList2:
case tListN:
return nList;
630 case tLambda:
case tPrimOp:
case tPrimOpApp:
return nFunction;
631 case tExternal:
return nExternal;
632 case tFloat:
return nFloat;
633 case tThunk:
case tApp:
return nThunk;
647 app.left = app.right = 0;
650 inline void mkInt(NixInt::Inner n)
655 inline void mkInt(NixInt n)
662 inline void mkBool(
bool b)
665 internalType = tBool;
669 inline void mkString(
const char * s,
const char * * context = 0)
671 internalType = tString;
673 string.context = context;
676 void mkString(std::string_view s);
678 void mkString(std::string_view s,
const NixStringContext & context);
680 void mkStringMove(
const char * s,
const NixStringContext & context);
682 void mkPath(
const SourcePath & path);
684 inline void mkPath(
const char * path)
687 internalType = tPath;
694 internalType = tNull;
697 inline void mkAttrs(Bindings * a)
700 internalType = tAttrs;
704 Value & mkAttrs(BindingsBuilder & bindings);
706 inline void mkList(
size_t size)
710 internalType = tList1;
712 internalType = tList2;
714 internalType = tListN;
719 inline void mkThunk(Env * e, Expr & ex)
721 internalType = tThunk;
733 inline void mkLambda(Env * e, ExprLambda * f)
735 internalType = tLambda;
740 inline void mkBlackhole()
742 internalType = tThunk;
743 thunk.expr = eBlackHoleAddr;
746 void mkPrimOp(PrimOp * p);
750 internalType = tPrimOpApp;
760 inline void mkExternal(ExternalValueBase * e)
763 internalType = tExternal;
767 inline void mkFloat(NixFloat n)
770 internalType = tFloat;
776 return internalType == tList1 || internalType == tList2 || internalType == tListN;
779 Value * * listElems()
781 return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
784 Value *
const * listElems()
const
786 return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
789 size_t listSize()
const
791 return internalType == tList1 ? 1 : internalType == tList2 ? 2 : bigList.size;
794 PosIdx determinePos(
const PosIdx pos)
const;
807 typedef Value *
const * iterator;
808 iterator _begin, _end;
809 iterator begin()
const {
return _begin; }
810 iterator end()
const {
return _end; }
813 auto begin = listElems();
814 return ListIterable { begin, begin + listSize() };
817 auto listItems()
const
819 struct ConstListIterable
821 typedef const Value *
const * iterator;
822 iterator _begin, _end;
823 iterator begin()
const {
return _begin; }
824 iterator end()
const {
return _end; }
827 auto begin = listElems();
828 return ConstListIterable { begin, begin + listSize() };
831 SourcePath path()
const
833 assert(internalType == tPath);
834 return SourcePath{CanonPath(_path)};
837 std::string_view str()
const
839 assert(internalType == tString);
840 return std::string_view(
string.s);
844using ValueVector = GcVector<Value *>;
845using ValueMap = GcMap<Symbol, Value *>;
846using ValueVectorMap = std::map<Symbol, ValueVector>;
Definition attr-set.hh:49
virtual JSON printValueAsJSON(EvalState &state, bool strict, NixStringContext &context, bool copyToStore=true) const
Definition value-to-json.cc:119
virtual std::string showType() const =0
virtual bool operator==(const ExternalValueBase &b) const
Definition eval.cc:2901
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:2893
virtual void printValueAsXML(EvalState &state, bool strict, bool location, XMLWriter &doc, NixStringContext &context, PathSet &drvsSeen, const PosIdx pos) const
Definition value-to-xml.cc:165
Definition xml-writer.hh:17
Definition concepts.hh:20
Options for printing Nix values.
Definition nixexpr.hh:333
Definition print-options.hh:38
Definition source-path.hh:23
Value(path_t, SourcePath const &path)
Definition value.hh:347
Value(floating_t, NixFloat f)
Definition value.hh:246
uintptr_t _empty[2]
Definition value.hh:537
static Value EMPTY_LIST
Definition value.hh:202
Value(boolean_t, bool b)
Definition value.hh:254
Value(string_t, char const *strPtr, char const **contextPtr=nullptr)
Definition value.hh:267
Value(null_t)
Constructs a nix language value of the singleton type "null".
Definition value.hh:417
Value(Value &&rhs)
Definition value.hh:490
Value(external_t, ExternalValueBase &external)
Definition value.hh:463
Value(path_t, char const *strPtr)
Definition value.hh:336
Value(list_t, std::span< Value * > items)
Definition value.hh:365
Value(integer_t, NixInt i)
Definition value.hh:233
Value & operator=(Value &&rhs)
Definition value.hh:502
Value()
Definition value.hh:226
Value(thunk_t, Env &env, Expr &expr)
Definition value.hh:437
Value(blackhole_t)
Constructs an evil thunk, whose evaluation represents infinite recursion.
Definition value.hh:481
Value(string_t, std::string_view copyFrom, NixStringContext const &context={})
Definition value.hh:277
ValueType type(bool invalidIsThunk=false) const
Definition value.hh:620
Value(lambda_t, Env &env, ExprLambda &lambda)
Definition value.hh:475
void clearValue()
Definition value.hh:645
Value(attrs_t, Bindings *bindings)
Definition value.hh:427
Value(list_t, SizedIterableT &items, TransformerT const &transformer)
Definition value.hh:393
Value(string_t, char const *strPtr, NixStringContext const &context)
Definition value.hh:308
Value(primOpApp_t, Value &lhs, Value &rhs)
Definition value.hh:449
PrimOp * primOpAppPrimOp() const
Definition value.cc:64
struct nix::Value::@0::@4 string
Value(app_t, Value &lhs, Value &rhs)
Definition value.hh:456
bool isTrivial() const
Definition value.cc:52
ValueType
Definition value.hh:49
std::shared_ptr< Value * > RootValue
Definition value.hh:851