1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 10:11:47 +02:00

libexpr: Format value.hh

The following commits will touch this file significantly, so
it's better to get the formatting out of the way first.
This commit is contained in:
Sergei Zimmerman 2025-06-28 15:30:38 +03:00
parent 04a731b4b9
commit ea32580c9b
No known key found for this signature in database
GPG key ID: A9B0B557CA632325
2 changed files with 158 additions and 87 deletions

View file

@ -256,7 +256,6 @@
''^src/libexpr/include/nix/expr/value-to-json\.hh$'' ''^src/libexpr/include/nix/expr/value-to-json\.hh$''
''^src/libexpr/value-to-xml\.cc$'' ''^src/libexpr/value-to-xml\.cc$''
''^src/libexpr/include/nix/expr/value-to-xml\.hh$'' ''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
''^src/libexpr/include/nix/expr/value\.hh$''
''^src/libexpr/value/context\.cc$'' ''^src/libexpr/value/context\.cc$''
''^src/libexpr/include/nix/expr/value/context\.hh$'' ''^src/libexpr/include/nix/expr/value/context\.hh$''
''^src/libfetchers/attrs\.cc$'' ''^src/libfetchers/attrs\.cc$''

View file

@ -17,7 +17,6 @@ namespace nix {
struct Value; struct Value;
class BindingsBuilder; class BindingsBuilder;
typedef enum { typedef enum {
tUninitialized = 0, tUninitialized = 0,
tInt = 1, tInt = 1,
@ -54,7 +53,7 @@ typedef enum {
nAttrs, nAttrs,
nList, nList,
nFunction, nFunction,
nExternal nExternal,
} ValueType; } ValueType;
class Bindings; class Bindings;
@ -81,15 +80,15 @@ using NixFloat = double;
*/ */
class ExternalValueBase class ExternalValueBase
{ {
friend std::ostream & operator << (std::ostream & str, const ExternalValueBase & v); friend std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v);
friend class Printer; friend class Printer;
protected: protected:
/** /**
* Print out the value * Print out the value
*/ */
virtual std::ostream & print(std::ostream & str) const = 0; virtual std::ostream & print(std::ostream & str) const = 0;
public: public:
/** /**
* Return a simple string describing the type * Return a simple string describing the type
*/ */
@ -104,41 +103,44 @@ class ExternalValueBase
* Coerce the value to a string. Defaults to uncoercable, i.e. throws an * Coerce the value to a string. Defaults to uncoercable, i.e. throws an
* error. * error.
*/ */
virtual std::string coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const; virtual std::string coerceToString(
EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const;
/** /**
* Compare to another value of the same type. Defaults to uncomparable, * Compare to another value of the same type. Defaults to uncomparable,
* i.e. always false. * i.e. always false.
*/ */
virtual bool operator ==(const ExternalValueBase & b) const noexcept; virtual bool operator==(const ExternalValueBase & b) const noexcept;
/** /**
* Print the value as JSON. Defaults to unconvertable, i.e. throws an error * Print the value as JSON. Defaults to unconvertable, i.e. throws an error
*/ */
virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict, virtual nlohmann::json
NixStringContext & context, bool copyToStore = true) const; printValueAsJSON(EvalState & state, bool strict, NixStringContext & context, bool copyToStore = true) const;
/** /**
* Print the value as XML. Defaults to unevaluated * Print the value as XML. Defaults to unevaluated
*/ */
virtual void printValueAsXML(EvalState & state, bool strict, bool location, virtual void printValueAsXML(
XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen, EvalState & state,
bool strict,
bool location,
XMLWriter & doc,
NixStringContext & context,
PathSet & drvsSeen,
const PosIdx pos) const; const PosIdx pos) const;
virtual ~ExternalValueBase() virtual ~ExternalValueBase() {};
{
};
}; };
std::ostream & operator << (std::ostream & str, const ExternalValueBase & v); std::ostream & operator<<(std::ostream & str, const ExternalValueBase & v);
class ListBuilder class ListBuilder
{ {
const size_t size; const size_t size;
Value * inlineElems[2] = {nullptr, nullptr}; Value * inlineElems[2] = {nullptr, nullptr};
public: public:
Value * * elems; Value ** elems;
ListBuilder(EvalState & state, size_t size); ListBuilder(EvalState & state, size_t size);
// NOTE: Can be noexcept because we are just copying integral values and // NOTE: Can be noexcept because we are just copying integral values and
@ -147,22 +149,28 @@ public:
: size(x.size) : size(x.size)
, inlineElems{x.inlineElems[0], x.inlineElems[1]} , inlineElems{x.inlineElems[0], x.inlineElems[1]}
, elems(size <= 2 ? inlineElems : x.elems) , elems(size <= 2 ? inlineElems : x.elems)
{ } {
}
Value * & operator [](size_t n) Value *& operator[](size_t n)
{ {
return elems[n]; return elems[n];
} }
typedef Value * * iterator; typedef Value ** iterator;
iterator begin() { return &elems[0]; } iterator begin()
iterator end() { return &elems[size]; } {
return &elems[0];
}
iterator end()
{
return &elems[size];
}
friend struct Value; friend struct Value;
}; };
struct Value struct Value
{ {
private: private:
@ -177,21 +185,36 @@ public:
*/ */
static Value * toPtr(SymbolStr str) noexcept; static Value * toPtr(SymbolStr str) noexcept;
void print(EvalState &state, std::ostream &str, PrintOptions options = PrintOptions {}); void print(EvalState & state, std::ostream & str, PrintOptions options = PrintOptions{});
// Functions needed to distinguish the type // Functions needed to distinguish the type
// These should be removed eventually, by putting the functionality that's // These should be removed eventually, by putting the functionality that's
// needed by callers into methods of this type // needed by callers into methods of this type
// type() == nThunk // type() == nThunk
inline bool isThunk() const { return internalType == tThunk; }; inline bool isThunk() const
inline bool isApp() const { return internalType == tApp; }; {
return internalType == tThunk;
};
inline bool isApp() const
{
return internalType == tApp;
};
inline bool isBlackhole() const; inline bool isBlackhole() const;
// type() == nFunction // type() == nFunction
inline bool isLambda() const { return internalType == tLambda; }; inline bool isLambda() const
inline bool isPrimOp() const { return internalType == tPrimOp; }; {
inline bool isPrimOpApp() const { return internalType == tPrimOpApp; }; return internalType == tLambda;
};
inline bool isPrimOp() const
{
return internalType == tPrimOp;
};
inline bool isPrimOpApp() const
{
return internalType == tPrimOpApp;
};
/** /**
* Strings in the evaluator carry a so-called `context` which * Strings in the evaluator carry a so-called `context` which
@ -215,26 +238,31 @@ public:
* For canonicity, the store paths should be in sorted order. * For canonicity, the store paths should be in sorted order.
*/ */
struct StringWithContext { struct StringWithContext
{
const char * c_str; const char * c_str;
const char * * context; // must be in sorted order const char ** context; // must be in sorted order
}; };
struct Path { struct Path
{
SourceAccessor * accessor; SourceAccessor * accessor;
const char * path; const char * path;
}; };
struct ClosureThunk { struct ClosureThunk
{
Env * env; Env * env;
Expr * expr; Expr * expr;
}; };
struct FunctionApplicationThunk { struct FunctionApplicationThunk
Value * left, * right; {
Value *left, *right;
}; };
struct Lambda { struct Lambda
{
Env * env; Env * env;
ExprLambda * fun; ExprLambda * fun;
}; };
@ -249,7 +277,8 @@ public:
Path path; Path path;
Bindings * attrs; Bindings * attrs;
struct { struct
{
size_t size; size_t size;
Value * const * elems; Value * const * elems;
} bigList; } bigList;
@ -275,18 +304,35 @@ public:
inline ValueType type(bool invalidIsThunk = false) const inline ValueType type(bool invalidIsThunk = false) const
{ {
switch (internalType) { switch (internalType) {
case tUninitialized: break; case tUninitialized:
case tInt: return nInt; break;
case tBool: return nBool; case tInt:
case tString: return nString; return nInt;
case tPath: return nPath; case tBool:
case tNull: return nNull; return nBool;
case tAttrs: return nAttrs; case tString:
case tList1: case tList2: case tListN: return nList; return nString;
case tLambda: case tPrimOp: case tPrimOpApp: return nFunction; case tPath:
case tExternal: return nExternal; return nPath;
case tFloat: return nFloat; case tNull:
case tThunk: case tApp: return nThunk; return nNull;
case tAttrs:
return nAttrs;
case tList1:
case tList2:
case tListN:
return nList;
case tLambda:
case tPrimOp:
case tPrimOpApp:
return nFunction;
case tExternal:
return nExternal;
case tFloat:
return nFloat;
case tThunk:
case tApp:
return nThunk;
} }
if (invalidIsThunk) if (invalidIsThunk)
return nThunk; return nThunk;
@ -317,17 +363,17 @@ public:
inline void mkInt(NixInt n) inline void mkInt(NixInt n)
{ {
finishValue(tInt, { .integer = n }); finishValue(tInt, {.integer = n});
} }
inline void mkBool(bool b) inline void mkBool(bool b)
{ {
finishValue(tBool, { .boolean = b }); finishValue(tBool, {.boolean = b});
} }
inline void mkString(const char * s, const char * * context = 0) inline void mkString(const char * s, const char ** context = 0)
{ {
finishValue(tString, { .string = { .c_str = s, .context = context } }); finishValue(tString, {.string = {.c_str = s, .context = context}});
} }
void mkString(std::string_view s); void mkString(std::string_view s);
@ -341,7 +387,7 @@ public:
inline void mkPath(SourceAccessor * accessor, const char * path) inline void mkPath(SourceAccessor * accessor, const char * path)
{ {
finishValue(tPath, { .path = { .accessor = accessor, .path = path } }); finishValue(tPath, {.path = {.accessor = accessor, .path = path}});
} }
inline void mkNull() inline void mkNull()
@ -351,7 +397,7 @@ public:
inline void mkAttrs(Bindings * a) inline void mkAttrs(Bindings * a)
{ {
finishValue(tAttrs, { .attrs = a }); finishValue(tAttrs, {.attrs = a});
} }
Value & mkAttrs(BindingsBuilder & bindings); Value & mkAttrs(BindingsBuilder & bindings);
@ -359,26 +405,26 @@ public:
void mkList(const ListBuilder & builder) void mkList(const ListBuilder & builder)
{ {
if (builder.size == 1) if (builder.size == 1)
finishValue(tList1, { .smallList = { builder.inlineElems[0] } }); finishValue(tList1, {.smallList = {builder.inlineElems[0]}});
else if (builder.size == 2) else if (builder.size == 2)
finishValue(tList2, { .smallList = { builder.inlineElems[0], builder.inlineElems[1] } }); finishValue(tList2, {.smallList = {builder.inlineElems[0], builder.inlineElems[1]}});
else else
finishValue(tListN, { .bigList = { .size = builder.size, .elems = builder.elems } }); finishValue(tListN, {.bigList = {.size = builder.size, .elems = builder.elems}});
} }
inline void mkThunk(Env * e, Expr * ex) inline void mkThunk(Env * e, Expr * ex)
{ {
finishValue(tThunk, { .thunk = { .env = e, .expr = ex } }); finishValue(tThunk, {.thunk = {.env = e, .expr = ex}});
} }
inline void mkApp(Value * l, Value * r) inline void mkApp(Value * l, Value * r)
{ {
finishValue(tApp, { .app = { .left = l, .right = r } }); finishValue(tApp, {.app = {.left = l, .right = r}});
} }
inline void mkLambda(Env * e, ExprLambda * f) inline void mkLambda(Env * e, ExprLambda * f)
{ {
finishValue(tLambda, { .lambda = { .env = e, .fun = f } }); finishValue(tLambda, {.lambda = {.env = e, .fun = f}});
} }
inline void mkBlackhole(); inline void mkBlackhole();
@ -387,7 +433,7 @@ public:
inline void mkPrimOpApp(Value * l, Value * r) inline void mkPrimOpApp(Value * l, Value * r)
{ {
finishValue(tPrimOpApp, { .primOpApp = { .left = l, .right = r } }); finishValue(tPrimOpApp, {.primOpApp = {.left = l, .right = r}});
} }
/** /**
@ -397,12 +443,12 @@ public:
inline void mkExternal(ExternalValueBase * e) inline void mkExternal(ExternalValueBase * e)
{ {
finishValue(tExternal, { .external = e }); finishValue(tExternal, {.external = e});
} }
inline void mkFloat(NixFloat n) inline void mkFloat(NixFloat n)
{ {
finishValue(tFloat, { .fpoint = n }); finishValue(tFloat, {.fpoint = n});
} }
bool isList() const bool isList() const
@ -438,9 +484,7 @@ public:
SourcePath path() const SourcePath path() const
{ {
assert(internalType == tPath); assert(internalType == tPath);
return SourcePath( return SourcePath(ref(pathAccessor()->shared_from_this()), CanonPath(CanonPath::unchecked_t(), pathStr()));
ref(pathAccessor()->shared_from_this()),
CanonPath(CanonPath::unchecked_t(), pathStr()));
} }
std::string_view string_view() const std::string_view string_view() const
@ -455,54 +499,77 @@ public:
return payload.string.c_str; return payload.string.c_str;
} }
const char * * context() const const char ** context() const
{ {
return payload.string.context; return payload.string.context;
} }
ExternalValueBase * external() const ExternalValueBase * external() const
{ return payload.external; } {
return payload.external;
}
const Bindings * attrs() const const Bindings * attrs() const
{ return payload.attrs; } {
return payload.attrs;
}
const PrimOp * primOp() const const PrimOp * primOp() const
{ return payload.primOp; } {
return payload.primOp;
}
bool boolean() const bool boolean() const
{ return payload.boolean; } {
return payload.boolean;
}
NixInt integer() const NixInt integer() const
{ return payload.integer; } {
return payload.integer;
}
NixFloat fpoint() const NixFloat fpoint() const
{ return payload.fpoint; } {
return payload.fpoint;
}
Lambda lambda() const Lambda lambda() const
{ return payload.lambda; } {
return payload.lambda;
}
ClosureThunk thunk() const ClosureThunk thunk() const
{ return payload.thunk; } {
return payload.thunk;
}
FunctionApplicationThunk primOpApp() const FunctionApplicationThunk primOpApp() const
{ return payload.primOpApp; } {
return payload.primOpApp;
}
FunctionApplicationThunk app() const FunctionApplicationThunk app() const
{ return payload.app; } {
return payload.app;
}
const char * pathStr() const const char * pathStr() const
{ return payload.path.path; } {
return payload.path.path;
}
SourceAccessor * pathAccessor() const SourceAccessor * pathAccessor() const
{ return payload.path.accessor; } {
return payload.path.accessor;
}
}; };
extern ExprBlackHole eBlackHole; extern ExprBlackHole eBlackHole;
bool Value::isBlackhole() const bool Value::isBlackhole() const
{ {
return internalType == tThunk && thunk().expr == (Expr*) &eBlackHole; return internalType == tThunk && thunk().expr == (Expr *) &eBlackHole;
} }
void Value::mkBlackhole() void Value::mkBlackhole()
@ -510,11 +577,16 @@ void Value::mkBlackhole()
mkThunk(nullptr, (Expr *) &eBlackHole); mkThunk(nullptr, (Expr *) &eBlackHole);
} }
typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector; typedef std::vector<Value *, traceable_allocator<Value *>> ValueVector;
typedef std::unordered_map<Symbol, Value *, std::hash<Symbol>, std::equal_to<Symbol>, traceable_allocator<std::pair<const Symbol, Value *>>> ValueMap; typedef std::unordered_map<
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>> ValueVectorMap; Symbol,
Value *,
std::hash<Symbol>,
std::equal_to<Symbol>,
traceable_allocator<std::pair<const Symbol, Value *>>>
ValueMap;
typedef std::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>>
ValueVectorMap;
/** /**
* A value allocated in traceable memory. * A value allocated in traceable memory.