libexpr: extend Value::print to allow limited depth

This commit is contained in:
Yingchi Long 2023-06-22 12:27:19 +08:00
parent c48277c1c1
commit 1400fde144
3 changed files with 81 additions and 10 deletions

View file

@ -95,11 +95,16 @@ RootValue allocRootValue(Value * v)
#endif #endif
} }
void Value::print(const SymbolTable & symbols, std::ostream & str, void Value::print(const SymbolTable &symbols, std::ostream &str,
std::set<const void *> * seen) const std::set<const void *> *seen, int depth) const
{ {
checkInterrupt(); checkInterrupt();
if (depth <= 0) {
str << "«too deep»";
return;
}
switch (internalType) { switch (internalType) {
case tInt: case tInt:
str << integer; str << integer;
@ -123,7 +128,7 @@ void Value::print(const SymbolTable & symbols, std::ostream & str,
str << "{ "; str << "{ ";
for (auto & i : attrs->lexicographicOrder(symbols)) { for (auto & i : attrs->lexicographicOrder(symbols)) {
str << symbols[i->name] << " = "; str << symbols[i->name] << " = ";
i->value->print(symbols, str, seen); i->value->print(symbols, str, seen, depth - 1);
str << "; "; str << "; ";
} }
str << "}"; str << "}";
@ -139,7 +144,7 @@ void Value::print(const SymbolTable & symbols, std::ostream & str,
str << "[ "; str << "[ ";
for (auto v2 : listItems()) { for (auto v2 : listItems()) {
if (v2) if (v2)
v2->print(symbols, str, seen); v2->print(symbols, str, seen, depth - 1);
else else
str << "(nullptr)"; str << "(nullptr)";
str << " "; str << " ";
@ -181,11 +186,10 @@ void Value::print(const SymbolTable & symbols, std::ostream & str,
} }
} }
void Value::print(const SymbolTable &symbols, std::ostream &str,
void Value::print(const SymbolTable & symbols, std::ostream & str, bool showRepeated) const bool showRepeated, int depth) const {
{
std::set<const void *> seen; std::set<const void *> seen;
print(symbols, str, showRepeated ? nullptr : &seen); print(symbols, str, showRepeated ? nullptr : &seen, depth);
} }
// Pretty print types for assertion errors // Pretty print types for assertion errors

View file

@ -167,4 +167,70 @@ TEST_F(ValuePrintingTests, vBlackhole)
test(vBlackhole, "«potential infinite recursion»"); test(vBlackhole, "«potential infinite recursion»");
} }
TEST_F(ValuePrintingTests, depthAttrs)
{
Value vOne;
vOne.mkInt(1);
Value vTwo;
vTwo.mkInt(2);
BindingsBuilder builder(state, state.allocBindings(10));
builder.insert(state.symbols.create("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo);
Value vAttrs;
vAttrs.mkAttrs(builder.finish());
BindingsBuilder builder2(state, state.allocBindings(10));
builder2.insert(state.symbols.create("one"), &vOne);
builder2.insert(state.symbols.create("two"), &vTwo);
builder2.insert(state.symbols.create("nested"), &vAttrs);
Value vNested;
vNested.mkAttrs(builder2.finish());
test(vNested, "{ nested = «too deep»; one = «too deep»; two = «too deep»; }", false, 1);
test(vNested, "{ nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; }", false, 2);
test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 3);
test(vNested, "{ nested = { one = 1; two = 2; }; one = 1; two = 2; }", false, 4);
}
TEST_F(ValuePrintingTests, depthList)
{
Value vOne;
vOne.mkInt(1);
Value vTwo;
vTwo.mkInt(2);
BindingsBuilder builder(state, state.allocBindings(10));
builder.insert(state.symbols.create("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo);
Value vAttrs;
vAttrs.mkAttrs(builder.finish());
BindingsBuilder builder2(state, state.allocBindings(10));
builder2.insert(state.symbols.create("one"), &vOne);
builder2.insert(state.symbols.create("two"), &vTwo);
builder2.insert(state.symbols.create("nested"), &vAttrs);
Value vNested;
vNested.mkAttrs(builder2.finish());
Value vList;
state.mkList(vList, 5);
vList.bigList.elems[0] = &vOne;
vList.bigList.elems[1] = &vTwo;
vList.bigList.elems[2] = &vNested;
vList.bigList.size = 3;
test(vList, "[ «too deep» «too deep» «too deep» ]", false, 1);
test(vList, "[ 1 2 { nested = «too deep»; one = «too deep»; two = «too deep»; } ]", false, 2);
test(vList, "[ 1 2 { nested = { one = «too deep»; two = «too deep»; }; one = 1; two = 2; } ]", false, 3);
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 4);
test(vList, "[ 1 2 { nested = { one = 1; two = 2; }; one = 1; two = 2; } ]", false, 5);
}
} // namespace nix } // namespace nix

View file

@ -2,6 +2,7 @@
///@file ///@file
#include <cassert> #include <cassert>
#include <climits>
#include "symbol-table.hh" #include "symbol-table.hh"
#include "value/context.hh" #include "value/context.hh"
@ -137,11 +138,11 @@ private:
friend std::string showType(const Value & v); friend std::string showType(const Value & v);
void print(const SymbolTable & symbols, std::ostream & str, std::set<const void *> * seen) const; void print(const SymbolTable &symbols, std::ostream &str, std::set<const void *> *seen, int depth) const;
public: public:
void print(const SymbolTable & symbols, std::ostream & str, bool showRepeated = false) const; void print(const SymbolTable &symbols, std::ostream &str, bool showRepeated = false, int depth = INT_MAX) const;
// 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