1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 06:01:48 +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/value-to-xml\.cc$''
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
''^src/libexpr/include/nix/expr/value\.hh$''
''^src/libexpr/value/context\.cc$''
''^src/libexpr/include/nix/expr/value/context\.hh$''
''^src/libfetchers/attrs\.cc$''

View file

@ -17,7 +17,6 @@ namespace nix {
struct Value;
class BindingsBuilder;
typedef enum {
tUninitialized = 0,
tInt = 1,
@ -54,7 +53,7 @@ typedef enum {
nAttrs,
nList,
nFunction,
nExternal
nExternal,
} ValueType;
class Bindings;
@ -81,15 +80,15 @@ using NixFloat = double;
*/
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;
protected:
protected:
/**
* Print out the value
*/
virtual std::ostream & print(std::ostream & str) const = 0;
public:
public:
/**
* 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
* 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,
* 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
*/
virtual nlohmann::json printValueAsJSON(EvalState & state, bool strict,
NixStringContext & context, bool copyToStore = true) const;
virtual nlohmann::json
printValueAsJSON(EvalState & state, bool strict, NixStringContext & context, bool copyToStore = true) const;
/**
* Print the value as XML. Defaults to unevaluated
*/
virtual void printValueAsXML(EvalState & state, bool strict, bool location,
XMLWriter & doc, NixStringContext & context, PathSet & drvsSeen,
virtual void printValueAsXML(
EvalState & state,
bool strict,
bool location,
XMLWriter & doc,
NixStringContext & context,
PathSet & drvsSeen,
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
{
const size_t size;
Value * inlineElems[2] = {nullptr, nullptr};
public:
Value * * elems;
Value ** elems;
ListBuilder(EvalState & state, size_t size);
// NOTE: Can be noexcept because we are just copying integral values and
@ -147,22 +149,28 @@ public:
: size(x.size)
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
, elems(size <= 2 ? inlineElems : x.elems)
{ }
{
}
Value * & operator [](size_t n)
Value *& operator[](size_t n)
{
return elems[n];
}
typedef Value * * iterator;
typedef Value ** iterator;
iterator begin() { return &elems[0]; }
iterator end() { return &elems[size]; }
iterator begin()
{
return &elems[0];
}
iterator end()
{
return &elems[size];
}
friend struct Value;
};
struct Value
{
private:
@ -177,21 +185,36 @@ public:
*/
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
// These should be removed eventually, by putting the functionality that's
// needed by callers into methods of this type
// type() == nThunk
inline bool isThunk() const { return internalType == tThunk; };
inline bool isApp() const { return internalType == tApp; };
inline bool isThunk() const
{
return internalType == tThunk;
};
inline bool isApp() const
{
return internalType == tApp;
};
inline bool isBlackhole() const;
// type() == nFunction
inline bool isLambda() const { return internalType == tLambda; };
inline bool isPrimOp() const { return internalType == tPrimOp; };
inline bool isPrimOpApp() const { return internalType == tPrimOpApp; };
inline bool isLambda() const
{
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
@ -215,26 +238,31 @@ public:
* For canonicity, the store paths should be in sorted order.
*/
struct StringWithContext {
struct StringWithContext
{
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;
const char * path;
};
struct ClosureThunk {
struct ClosureThunk
{
Env * env;
Expr * expr;
};
struct FunctionApplicationThunk {
Value * left, * right;
struct FunctionApplicationThunk
{
Value *left, *right;
};
struct Lambda {
struct Lambda
{
Env * env;
ExprLambda * fun;
};
@ -249,7 +277,8 @@ public:
Path path;
Bindings * attrs;
struct {
struct
{
size_t size;
Value * const * elems;
} bigList;
@ -275,18 +304,35 @@ public:
inline ValueType type(bool invalidIsThunk = false) const
{
switch (internalType) {
case tUninitialized: break;
case tInt: return nInt;
case tBool: return nBool;
case tString: return nString;
case tPath: return nPath;
case tNull: 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;
case tUninitialized:
break;
case tInt:
return nInt;
case tBool:
return nBool;
case tString:
return nString;
case tPath:
return nPath;
case tNull:
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)
return nThunk;
@ -317,17 +363,17 @@ public:
inline void mkInt(NixInt n)
{
finishValue(tInt, { .integer = n });
finishValue(tInt, {.integer = n});
}
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);
@ -341,7 +387,7 @@ public:
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()
@ -351,7 +397,7 @@ public:
inline void mkAttrs(Bindings * a)
{
finishValue(tAttrs, { .attrs = a });
finishValue(tAttrs, {.attrs = a});
}
Value & mkAttrs(BindingsBuilder & bindings);
@ -359,26 +405,26 @@ public:
void mkList(const ListBuilder & builder)
{
if (builder.size == 1)
finishValue(tList1, { .smallList = { builder.inlineElems[0] } });
finishValue(tList1, {.smallList = {builder.inlineElems[0]}});
else if (builder.size == 2)
finishValue(tList2, { .smallList = { builder.inlineElems[0], builder.inlineElems[1] } });
finishValue(tList2, {.smallList = {builder.inlineElems[0], builder.inlineElems[1]}});
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)
{
finishValue(tThunk, { .thunk = { .env = e, .expr = ex } });
finishValue(tThunk, {.thunk = {.env = e, .expr = ex}});
}
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)
{
finishValue(tLambda, { .lambda = { .env = e, .fun = f } });
finishValue(tLambda, {.lambda = {.env = e, .fun = f}});
}
inline void mkBlackhole();
@ -387,7 +433,7 @@ public:
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)
{
finishValue(tExternal, { .external = e });
finishValue(tExternal, {.external = e});
}
inline void mkFloat(NixFloat n)
{
finishValue(tFloat, { .fpoint = n });
finishValue(tFloat, {.fpoint = n});
}
bool isList() const
@ -438,9 +484,7 @@ public:
SourcePath path() const
{
assert(internalType == tPath);
return SourcePath(
ref(pathAccessor()->shared_from_this()),
CanonPath(CanonPath::unchecked_t(), pathStr()));
return SourcePath(ref(pathAccessor()->shared_from_this()), CanonPath(CanonPath::unchecked_t(), pathStr()));
}
std::string_view string_view() const
@ -455,54 +499,77 @@ public:
return payload.string.c_str;
}
const char * * context() const
const char ** context() const
{
return payload.string.context;
}
ExternalValueBase * external() const
{ return payload.external; }
{
return payload.external;
}
const Bindings * attrs() const
{ return payload.attrs; }
{
return payload.attrs;
}
const PrimOp * primOp() const
{ return payload.primOp; }
{
return payload.primOp;
}
bool boolean() const
{ return payload.boolean; }
{
return payload.boolean;
}
NixInt integer() const
{ return payload.integer; }
{
return payload.integer;
}
NixFloat fpoint() const
{ return payload.fpoint; }
{
return payload.fpoint;
}
Lambda lambda() const
{ return payload.lambda; }
{
return payload.lambda;
}
ClosureThunk thunk() const
{ return payload.thunk; }
{
return payload.thunk;
}
FunctionApplicationThunk primOpApp() const
{ return payload.primOpApp; }
{
return payload.primOpApp;
}
FunctionApplicationThunk app() const
{ return payload.app; }
{
return payload.app;
}
const char * pathStr() const
{ return payload.path.path; }
{
return payload.path.path;
}
SourceAccessor * pathAccessor() const
{ return payload.path.accessor; }
{
return payload.path.accessor;
}
};
extern ExprBlackHole eBlackHole;
bool Value::isBlackhole() const
{
return internalType == tThunk && thunk().expr == (Expr*) &eBlackHole;
return internalType == tThunk && thunk().expr == (Expr *) &eBlackHole;
}
void Value::mkBlackhole()
@ -510,11 +577,16 @@ void Value::mkBlackhole()
mkThunk(nullptr, (Expr *) &eBlackHole);
}
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::map<Symbol, ValueVector, std::less<Symbol>, traceable_allocator<std::pair<const Symbol, ValueVector>>> ValueVectorMap;
typedef std::unordered_map<
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.