nix-super/src/libexpr/value-to-xml.cc

186 lines
5.5 KiB
C++
Raw Normal View History

2010-04-07 16:59:45 +03:00
#include "value-to-xml.hh"
2006-08-24 17:16:55 +03:00
#include "xml-writer.hh"
#include "eval-inline.hh"
#include "util.hh"
2006-08-24 17:16:55 +03:00
#include <cstdlib>
2006-08-24 17:16:55 +03:00
namespace nix {
2015-07-17 20:24:28 +03:00
2006-08-24 17:16:55 +03:00
static XMLAttrs singletonAttrs(const string & name, const string & value)
{
XMLAttrs attrs;
attrs[name] = value;
return attrs;
}
2010-05-07 17:46:47 +03:00
static void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
const Pos & pos);
2010-05-07 17:46:47 +03:00
static void posToXML(XMLAttrs & xmlAttrs, const Pos & pos)
{
xmlAttrs["path"] = pos.file;
xmlAttrs["line"] = (format("%1%") % pos.line).str();
xmlAttrs["column"] = (format("%1%") % pos.column).str();
}
static void showAttrs(EvalState & state, bool strict, bool location,
Bindings & attrs, XMLWriter & doc, PathSet & context, PathSet & drvsSeen)
{
StringSet names;
2015-07-17 20:24:28 +03:00
for (auto & i : attrs)
names.insert(i.name);
for (auto & i : names) {
Attr & a(*attrs.find(state.symbols.create(i)));
2010-05-07 17:46:47 +03:00
XMLAttrs xmlAttrs;
2015-07-17 20:24:28 +03:00
xmlAttrs["name"] = i;
if (location && a.pos != ptr(&noPos)) posToXML(xmlAttrs, *a.pos);
2015-07-17 20:24:28 +03:00
2010-05-07 17:46:47 +03:00
XMLOpenElement _(doc, "attr", xmlAttrs);
printValueAsXML(state, strict, location,
*a.value, doc, context, drvsSeen, *a.pos);
}
}
2010-05-07 17:46:47 +03:00
static void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
const Pos & pos)
2006-08-24 17:16:55 +03:00
{
checkInterrupt();
if (strict) state.forceValue(v, pos);
2015-07-17 20:24:28 +03:00
switch (v.type()) {
2006-08-24 17:16:55 +03:00
case nInt:
doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str()));
break;
2006-08-24 17:16:55 +03:00
case nBool:
doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false"));
break;
2006-08-24 17:16:55 +03:00
case nString:
/* !!! show the context? */
copyContext(v, context);
doc.writeEmptyElement("string", singletonAttrs("value", v.string.s));
break;
2006-08-24 17:16:55 +03:00
case nPath:
doc.writeEmptyElement("path", singletonAttrs("value", v.path));
break;
case nNull:
doc.writeEmptyElement("null");
break;
case nAttrs:
if (state.isDerivation(v)) {
XMLAttrs xmlAttrs;
2015-07-17 20:24:28 +03:00
Bindings::iterator a = v.attrs->find(state.symbols.create("derivation"));
Path drvPath;
a = v.attrs->find(state.sDrvPath);
2010-05-07 17:46:47 +03:00
if (a != v.attrs->end()) {
if (strict) state.forceValue(*a->value, *a->pos);
if (a->value->type() == nString)
xmlAttrs["drvPath"] = drvPath = a->value->string.s;
2010-05-07 17:46:47 +03:00
}
2015-07-17 20:24:28 +03:00
a = v.attrs->find(state.sOutPath);
2010-05-07 17:46:47 +03:00
if (a != v.attrs->end()) {
if (strict) state.forceValue(*a->value, *a->pos);
if (a->value->type() == nString)
xmlAttrs["outPath"] = a->value->string.s;
2010-05-07 17:46:47 +03:00
}
XMLOpenElement _(doc, "derivation", xmlAttrs);
if (drvPath != "" && drvsSeen.insert(drvPath).second)
2010-05-07 17:46:47 +03:00
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
else
doc.writeEmptyElement("repeated");
}
else {
XMLOpenElement _(doc, "attrs");
2010-05-07 17:46:47 +03:00
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
}
2015-07-17 20:24:28 +03:00
break;
case nList: {
XMLOpenElement _(doc, "list");
for (auto v2 : v.listItems())
printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos);
break;
}
case nFunction: {
if (!v.isLambda()) {
// FIXME: Serialize primops and primopapps
doc.writeEmptyElement("unevaluated");
break;
}
2010-05-07 17:46:47 +03:00
XMLAttrs xmlAttrs;
if (location) posToXML(xmlAttrs, v.lambda.fun->pos);
XMLOpenElement _(doc, "function", xmlAttrs);
2015-07-17 20:24:28 +03:00
if (v.lambda.fun->hasFormals()) {
XMLAttrs attrs;
if (!v.lambda.fun->arg.empty()) attrs["name"] = v.lambda.fun->arg;
if (v.lambda.fun->formals->ellipsis) attrs["ellipsis"] = "1";
XMLOpenElement _(doc, "attrspat", attrs);
defer formals duplicate check for incresed efficiency all round if we defer the duplicate argument check for lambda formals we can use more efficient data structures for the formals set, and we can get rid of the duplication of formals names to boot. instead of a list of formals we've seen and a set of names we'll keep a vector instead and run a sort+dupcheck step before moving the parsed formals into a newly created lambda. this improves performance on search and rebuild by ~1%, pure parsing gains more (about 4%). this does reorder lambda arguments in the xml output, but the output is still stable. this shouldn't be a problem since argument order is not semantically important anyway. before nix search --no-eval-cache --offline ../nixpkgs hello Time (mean ± σ): 8.550 s ± 0.060 s [User: 6.470 s, System: 1.664 s] Range (min … max): 8.435 s … 8.666 s 20 runs nix eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix Time (mean ± σ): 346.7 ms ± 2.1 ms [User: 312.4 ms, System: 34.2 ms] Range (min … max): 343.8 ms … 353.4 ms 20 runs nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' Time (mean ± σ): 2.720 s ± 0.031 s [User: 2.415 s, System: 0.231 s] Range (min … max): 2.662 s … 2.780 s 20 runs after nix search --no-eval-cache --offline ../nixpkgs hello Time (mean ± σ): 8.462 s ± 0.063 s [User: 6.398 s, System: 1.661 s] Range (min … max): 8.339 s … 8.542 s 20 runs nix eval -f ../nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix Time (mean ± σ): 329.1 ms ± 1.4 ms [User: 296.8 ms, System: 32.3 ms] Range (min … max): 326.1 ms … 330.8 ms 20 runs nix eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system' Time (mean ± σ): 2.687 s ± 0.035 s [User: 2.392 s, System: 0.228 s] Range (min … max): 2.626 s … 2.754 s 20 runs
2022-01-19 17:49:02 +02:00
for (auto & i : v.lambda.fun->formals->lexicographicOrder())
2015-07-17 20:24:28 +03:00
doc.writeEmptyElement("attr", singletonAttrs("name", i.name));
} else
doc.writeEmptyElement("varpat", singletonAttrs("name", v.lambda.fun->arg));
2015-07-17 20:24:28 +03:00
break;
2006-08-24 17:16:55 +03:00
}
case nExternal:
v.external->printValueAsXML(state, strict, location, doc, context, drvsSeen, pos);
break;
case nFloat:
doc.writeEmptyElement("float", singletonAttrs("value", (format("%1%") % v.fpoint).str()));
break;
case nThunk:
doc.writeEmptyElement("unevaluated");
2006-08-24 17:16:55 +03:00
}
}
void ExternalValueBase::printValueAsXML(EvalState & state, bool strict,
bool location, XMLWriter & doc, PathSet & context, PathSet & drvsSeen,
const Pos & pos) const
{
doc.writeEmptyElement("unevaluated");
}
2010-05-07 17:46:47 +03:00
void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, std::ostream & out, PathSet & context, const Pos & pos)
2006-08-24 17:16:55 +03:00
{
XMLWriter doc(true, out);
XMLOpenElement root(doc, "expr");
2015-07-17 20:24:28 +03:00
PathSet drvsSeen;
printValueAsXML(state, strict, location, v, doc, context, drvsSeen, pos);
2006-08-24 17:16:55 +03:00
}
2015-07-17 20:24:28 +03:00
}