From 8a10360c912bc344ea9ce7f8871a47a6e036552f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 25 Mar 2010 12:19:41 +0000 Subject: * Simplify @-patterns: only `{attrs}@name' or `name@{attrs}' are now allowed. So `name1@name2', `{attrs1}@{attrs2}' and so on are now no longer legal. This is no big loss because they were not useful anyway. This also changes the output of builtins.toXML for @-patterns slightly. --- src/libexpr/expr-to-xml.cc | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'src/libexpr/expr-to-xml.cc') diff --git a/src/libexpr/expr-to-xml.cc b/src/libexpr/expr-to-xml.cc index e401001ead..9b3062804e 100644 --- a/src/libexpr/expr-to-xml.cc +++ b/src/libexpr/expr-to-xml.cc @@ -44,23 +44,19 @@ static void printPatternAsXML(Pattern pat, XMLWriter & doc) { ATerm name; ATermList formals; - Pattern pat1, pat2; ATermBool ellipsis; if (matchVarPat(pat, name)) doc.writeEmptyElement("varpat", singletonAttrs("name", aterm2String(name))); - else if (matchAttrsPat(pat, formals, ellipsis)) { - XMLOpenElement _(doc, "attrspat"); + else if (matchAttrsPat(pat, formals, ellipsis, name)) { + XMLAttrs attrs; + if (name != sNoAlias) attrs["name"] = aterm2String(name); + if (ellipsis == eTrue) attrs["ellipsis"] = "1"; + XMLOpenElement _(doc, "attrspat", attrs); for (ATermIterator i(formals); i; ++i) { Expr name; ATerm dummy; if (!matchFormal(*i, name, dummy)) abort(); doc.writeEmptyElement("attr", singletonAttrs("name", aterm2String(name))); } - if (ellipsis == eTrue) doc.writeEmptyElement("ellipsis"); - } - else if (matchAtPat(pat, pat1, pat2)) { - XMLOpenElement _(doc, "at"); - printPatternAsXML(pat1, doc); - printPatternAsXML(pat2, doc); } } -- cgit 1.4.1 From fc92244ba81d884e099d467a3b82fbdcbff7fc40 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 7 Apr 2010 13:55:46 +0000 Subject: * Implemented the primops necessary for generating the NixOS manual. --- src/libexpr/eval-test.cc | 5 +- src/libexpr/eval.cc | 52 ++++++------ src/libexpr/eval.hh | 21 +++-- src/libexpr/expr-to-xml.cc | 147 ++++++++++++++++----------------- src/libexpr/expr-to-xml.hh | 5 +- src/libexpr/get-drvs.cc | 7 +- src/libexpr/primops.cc | 64 +++++++------- src/nix-instantiate/nix-instantiate.cc | 3 +- 8 files changed, 159 insertions(+), 145 deletions(-) (limited to 'src/libexpr/expr-to-xml.cc') diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc index 3399aedc4c..eac95094fd 100644 --- a/src/libexpr/eval-test.cc +++ b/src/libexpr/eval-test.cc @@ -16,7 +16,8 @@ void doTest(string s) Expr e = parseExprFromString(state, s, absPath(".")); printMsg(lvlError, format(">>>>> %1%") % e); Value v; - state.strictEval(e, v); + state.eval(e, v); + state.strictForceValue(v); printMsg(lvlError, format("result: %1%") % v); } @@ -76,6 +77,8 @@ void run(Strings args) doTest("let x = 1; as = rec { inherit x; y = as.x; }; in as.y"); doTest("let as = { x = 1; }; bs = rec { inherit (as) x; y = x; }; in bs.y"); doTest("let as = rec { inherit (y) x; y = { x = 1; }; }; in as.x"); + doTest("builtins.toXML 123"); + doTest("builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }"); } diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 5f6ab2655a..0d18c55227 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -302,6 +302,8 @@ void EvalState::eval(Env & env, Expr e, Value & v) //debug(format("eval: %1%") % e); + checkInterrupt(); + nrEvaluated++; Sym name; @@ -639,28 +641,6 @@ bool EvalState::evalBool(Env & env, Expr e) } -void EvalState::strictEval(Env & env, Expr e, Value & v) -{ - eval(env, e, v); - - if (v.type == tAttrs) { - foreach (Bindings::iterator, i, *v.attrs) - forceValue(i->second); - } - - else if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) - forceValue(v.list.elems[n]); - } -} - - -void EvalState::strictEval(Expr e, Value & v) -{ - strictEval(baseEnv, e, v); -} - - void EvalState::forceValue(Value & v) { if (v.type == tThunk) { @@ -678,6 +658,22 @@ void EvalState::forceValue(Value & v) } +void EvalState::strictForceValue(Value & v) +{ + forceValue(v); + + if (v.type == tAttrs) { + foreach (Bindings::iterator, i, *v.attrs) + strictForceValue(i->second); + } + + else if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) + strictForceValue(v.list.elems[n]); + } +} + + int EvalState::forceInt(Value & v) { forceValue(v); @@ -750,6 +746,14 @@ string EvalState::forceStringNoCtx(Value & v) } +bool EvalState::isDerivation(Value & v) +{ + if (v.type != tAttrs) return false; + Bindings::iterator i = v.attrs->find(toATerm("type")); + return i != v.attrs->end() && forceStringNoCtx(i->second) == "derivation"; +} + + string EvalState::coerceToString(Value & v, PathSet & context, bool coerceMore, bool copyToStore) { @@ -769,7 +773,7 @@ string EvalState::coerceToString(Value & v, PathSet & context, if (!copyToStore) return path; - if (isDerivation(path)) + if (nix::isDerivation(path)) throw EvalError(format("file names are not allowed to end in `%1%'") % drvExtension); @@ -1415,5 +1419,5 @@ void EvalState::printStats() printATermMapStats(); } - + } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index ae6b2106f4..a42b9ebeba 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -169,17 +169,16 @@ public: type. */ bool evalBool(Env & env, Expr e); - /* Evaluate an expression, and recursively evaluate list elements - and attributes. */ - void strictEval(Expr e, Value & v); - void strictEval(Env & env, Expr e, Value & v); - /* If `v' is a thunk, enter it and overwrite `v' with the result of the evaluation of the thunk. If `v' is a delayed function application, call the function and overwrite `v' with the result. Otherwise, this is a no-op. */ void forceValue(Value & v); + /* Force a value, then recursively force list elements and + attributes. */ + void strictForceValue(Value & v); + /* Force `v', and then verify that it has the expected type. */ int forceInt(Value & v); bool forceBool(Value & v); @@ -190,6 +189,10 @@ public: string forceString(Value & v, PathSet & context); string forceStringNoCtx(Value & v); + /* Return true iff the value `v' denotes a derivation (i.e. a + set with attribute `type = "derivation"'). */ + bool isDerivation(Value & v); + /* String coercion. Converts strings, paths and derivations to a string. If `coerceMore' is set, also converts nulls, integers, booleans and lists to a string. If `copyToStore' is set, @@ -219,10 +222,10 @@ private: elements and attributes are compared recursively. */ bool eqValues(Value & v1, Value & v2); - void callFunction(Value & fun, Value & arg, Value & v); - public: + void callFunction(Value & fun, Value & arg, Value & v); + /* Allocation primitives. */ Value * allocValues(unsigned int count); Env & allocEnv(); @@ -237,6 +240,10 @@ public: }; +/* Return a string representing the type of the value `v'. */ +string showType(Value & v); + + #if 0 /* Evaluate an expression to normal form. */ Expr evalExpr(EvalState & state, Expr e); diff --git a/src/libexpr/expr-to-xml.cc b/src/libexpr/expr-to-xml.cc index 9b3062804e..ad68739c39 100644 --- a/src/libexpr/expr-to-xml.cc +++ b/src/libexpr/expr-to-xml.cc @@ -18,24 +18,19 @@ static XMLAttrs singletonAttrs(const string & name, const string & value) } -/* set is safe because all the expressions are also reachable - from the stack, therefore can't be garbage-collected. */ -typedef set ExprSet; +static void printValueAsXML(EvalState & state, bool strict, Value & v, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen); -static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context, - ExprSet & drvsSeen); - - -static void showAttrs(const ATermMap & attrs, XMLWriter & doc, - PathSet & context, ExprSet & drvsSeen) +static void showAttrs(EvalState & state, bool strict, Bindings & attrs, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen) { StringSet names; - for (ATermMap::const_iterator i = attrs.begin(); i != attrs.end(); ++i) - names.insert(aterm2String(i->key)); - for (StringSet::iterator i = names.begin(); i != names.end(); ++i) { + foreach (Bindings::iterator, i, attrs) + names.insert(aterm2String(i->first)); + foreach (StringSet::iterator, i, names) { XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); - printTermAsXML(attrs.get(toATerm(*i)), doc, context, drvsSeen); + printValueAsXML(state, strict, attrs[toATerm(*i)], doc, context, drvsSeen); } } @@ -61,91 +56,93 @@ static void printPatternAsXML(Pattern pat, XMLWriter & doc) } -static void printTermAsXML(Expr e, XMLWriter & doc, PathSet & context, - ExprSet & drvsSeen) +static void printValueAsXML(EvalState & state, bool strict, Value & v, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen) { - XMLAttrs attrs; - string s; - ATerm s2; - int i; - ATermList as, es; - ATerm pat, body, pos; - checkInterrupt(); - if (matchStr(e, s, context)) /* !!! show the context? */ - doc.writeEmptyElement("string", singletonAttrs("value", s)); - - else if (matchPath(e, s2)) - doc.writeEmptyElement("path", singletonAttrs("value", aterm2String(s2))); - - else if (matchNull(e)) - doc.writeEmptyElement("null"); + if (strict) state.forceValue(v); + + switch (v.type) { - else if (matchInt(e, i)) - doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % i).str())); + case tInt: + doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str())); + break; - else if (e == eTrue) - doc.writeEmptyElement("bool", singletonAttrs("value", "true")); + case tBool: + doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false")); + break; - else if (e == eFalse) - doc.writeEmptyElement("bool", singletonAttrs("value", "false")); + case tString: + /* !!! show the context? */ + doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); + break; - else if (matchAttrs(e, as)) { - ATermMap attrs; - queryAllAttrs(e, attrs); + case tPath: + doc.writeEmptyElement("path", singletonAttrs("value", v.path)); + break; - Expr a = attrs.get(toATerm("type")); - if (a && matchStr(a, s, context) && s == "derivation") { + case tNull: + doc.writeEmptyElement("null"); + break; - XMLAttrs xmlAttrs; - Path outPath, drvPath; + case tAttrs: + if (state.isDerivation(v)) { + XMLAttrs xmlAttrs; - a = attrs.get(toATerm("drvPath")); - if (matchStr(a, drvPath, context)) - xmlAttrs["drvPath"] = drvPath; - - a = attrs.get(toATerm("outPath")); - if (matchStr(a, outPath, context)) - xmlAttrs["outPath"] = outPath; + Bindings::iterator a = v.attrs->find(toATerm("derivation")); + + Path drvPath; + a = v.attrs->find(toATerm("drvPath")); + if (a != v.attrs->end() && a->second.type == tString) + xmlAttrs["drvPath"] = drvPath = a->second.string.s; - XMLOpenElement _(doc, "derivation", xmlAttrs); + a = v.attrs->find(toATerm("outPath")); + if (a != v.attrs->end() && a->second.type == tString) + xmlAttrs["outPath"] = a->second.string.s; + + XMLOpenElement _(doc, "derivation", xmlAttrs); + + if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { + drvsSeen.insert(drvPath); + showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); + } else + doc.writeEmptyElement("repeated"); + } + + else { + XMLOpenElement _(doc, "attrs"); + showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); + } + + break; - if (drvsSeen.find(e) == drvsSeen.end()) { - drvsSeen.insert(e); - showAttrs(attrs, doc, context, drvsSeen); - } else - doc.writeEmptyElement("repeated"); + case tList: { + XMLOpenElement _(doc, "list"); + for (unsigned int n = 0; n < v.list.length; ++n) + printValueAsXML(state, strict, v.list.elems[n], doc, context, drvsSeen); + break; } - else { - XMLOpenElement _(doc, "attrs"); - showAttrs(attrs, doc, context, drvsSeen); + case tLambda: { + XMLOpenElement _(doc, "function"); + printPatternAsXML(v.lambda.pat, doc); + break; } - } - else if (matchList(e, es)) { - XMLOpenElement _(doc, "list"); - for (ATermIterator i(es); i; ++i) - printTermAsXML(*i, doc, context, drvsSeen); + default: + doc.writeEmptyElement("unevaluated"); } - - else if (matchFunction(e, pat, body, pos)) { - XMLOpenElement _(doc, "function"); - printPatternAsXML(pat, doc); - } - - else - doc.writeEmptyElement("unevaluated"); } -void printTermAsXML(Expr e, std::ostream & out, PathSet & context) +void printValueAsXML(EvalState & state, bool strict, + Value & v, std::ostream & out, PathSet & context) { XMLWriter doc(true, out); XMLOpenElement root(doc, "expr"); - ExprSet drvsSeen; - printTermAsXML(e, doc, context, drvsSeen); + PathSet drvsSeen; + printValueAsXML(state, strict, v, doc, context, drvsSeen); } diff --git a/src/libexpr/expr-to-xml.hh b/src/libexpr/expr-to-xml.hh index 36b8e40424..8f094185c4 100644 --- a/src/libexpr/expr-to-xml.hh +++ b/src/libexpr/expr-to-xml.hh @@ -5,11 +5,12 @@ #include #include "nixexpr.hh" -#include "aterm.hh" +#include "eval.hh" namespace nix { -void printTermAsXML(Expr e, std::ostream & out, PathSet & context); +void printValueAsXML(EvalState & state, bool strict, + Value & v, std::ostream & out, PathSet & context); } diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index f02392bed5..6e651d77f0 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -105,10 +105,7 @@ static bool getDerivation(EvalState & state, Value & v, { try { state.forceValue(v); - if (v.type != tAttrs) return true; - - Bindings::iterator i = v.attrs->find(toATerm("type")); - if (i == v.attrs->end() || state.forceStringNoCtx(i->second) != "derivation") return true; + if (!state.isDerivation(v)) return true; /* Remove spurious duplicates (e.g., an attribute set like `rec { x = derivation {...}; y = x;}'. */ @@ -117,7 +114,7 @@ static bool getDerivation(EvalState & state, Value & v, DrvInfo drv; - i = v.attrs->find(toATerm("name")); + Bindings::iterator i = v.attrs->find(toATerm("name")); /* !!! We really would like to have a decent back trace here. */ if (i == v.attrs->end()) throw TypeError("derivation name missing"); drv.name = state.forceStringNoCtx(i->second); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 98a31dc3a5..5fa2418b5f 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -538,7 +538,6 @@ static void prim_readFile(EvalState & state, Value * * args, Value & v) *************************************************************/ -#if 0 /* Convert the argument (which can be any Nix expression) to an XML representation returned in a string. Not all Nix expressions can be sensibly or completely represented (e.g., functions). */ @@ -546,10 +545,9 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) { std::ostringstream out; PathSet context; - printTermAsXML(strictEvalExpr(state, args[0]), out, context); - return makeStr(out.str(), context); + printValueAsXML(state, true, *args[0], out, context); + mkString(v, out.str(), context); } -#endif /* Store a string in the Nix store as a source file that can be used @@ -582,13 +580,12 @@ static void prim_toFile(EvalState & state, Value * * args, Value & v) } -#if 0 struct FilterFromExpr : PathFilter { EvalState & state; - Expr filter; + Value & filter; - FilterFromExpr(EvalState & state, Expr filter) + FilterFromExpr(EvalState & state, Value & filter) : state(state), filter(filter) { } @@ -599,17 +596,25 @@ struct FilterFromExpr : PathFilter if (lstat(path.c_str(), &st)) throw SysError(format("getting attributes of path `%1%'") % path); - Expr call = - makeCall( - makeCall(filter, makeStr(path)), - makeStr( - S_ISREG(st.st_mode) ? "regular" : - S_ISDIR(st.st_mode) ? "directory" : - S_ISLNK(st.st_mode) ? "symlink" : - "unknown" /* not supported, will fail! */ - )); - - return evalBool(state, call); + /* Call the filter function. The first argument is the path, + the second is a string indicating the type of the file. */ + Value arg1; + mkString(arg1, path); + + Value fun2; + state.callFunction(filter, arg1, fun2); + + Value arg2; + mkString(arg2, + S_ISREG(st.st_mode) ? "regular" : + S_ISDIR(st.st_mode) ? "directory" : + S_ISLNK(st.st_mode) ? "symlink" : + "unknown" /* not supported, will fail! */); + + Value res; + state.callFunction(fun2, arg2, res); + + return state.forceBool(res); } }; @@ -617,19 +622,22 @@ struct FilterFromExpr : PathFilter static void prim_filterSource(EvalState & state, Value * * args, Value & v) { PathSet context; - Path path = coerceToPath(state, args[1], context); + Path path = state.coerceToPath(*args[1], context); if (!context.empty()) throw EvalError(format("string `%1%' cannot refer to other paths") % path); - FilterFromExpr filter(state, args[0]); + state.forceValue(*args[0]); + if (args[0]->type != tLambda) + throw TypeError(format("first argument in call to `filterSource' is not a function but %1%") % showType(*args[0])); + + FilterFromExpr filter(state, *args[0]); Path dstPath = readOnlyMode ? computeStorePathForPath(path, true, htSHA256, filter).first : store->addToStore(path, true, htSHA256, filter); - return makeStr(dstPath, singleton(dstPath)); + mkString(v, dstPath, singleton(dstPath)); } -#endif /************************************************************* @@ -927,15 +935,15 @@ static void prim_stringLength(EvalState & state, Value * * args, Value & v) } -#if 0 static void prim_unsafeDiscardStringContext(EvalState & state, Value * * args, Value & v) { PathSet context; - string s = coerceToString(state, args[0], context); - return makeStr(s, PathSet()); + string s = state.coerceToString(*args[0], context); + mkString(v, s, PathSet()); } +#if 0 /* Sometimes we want to pass a derivation path (i.e. pkg.drvPath) to a builder without causing the derivation to be built (for instance, in the derivation that builds NARs in nix-push, when doing @@ -1053,13 +1061,9 @@ void EvalState::createBaseEnv() addPrimOp("__readFile", 1, prim_readFile); // Creating files -#if 0 addPrimOp("__toXML", 1, prim_toXML); -#endif addPrimOp("__toFile", 2, prim_toFile); -#if 0 addPrimOp("__filterSource", 2, prim_filterSource); -#endif // Attribute sets addPrimOp("__attrNames", 1, prim_attrNames); @@ -1091,8 +1095,8 @@ void EvalState::createBaseEnv() addPrimOp("toString", 1, prim_toString); addPrimOp("__substring", 3, prim_substring); addPrimOp("__stringLength", 1, prim_stringLength); -#if 0 addPrimOp("__unsafeDiscardStringContext", 1, prim_unsafeDiscardStringContext); +#if 0 addPrimOp("__unsafeDiscardOutputDependency", 1, prim_unsafeDiscardOutputDependency); #endif diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index a71998de24..2f41fa81b5 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -75,7 +75,8 @@ void processExpr(EvalState & state, const Strings & attrPaths, std::cout << format("%1%\n") % canonicaliseExpr(e); else { Value v; - if (strict) state.strictEval(e, v); else state.eval(e, v); + state.eval(e, v); + if (strict) state.strictForceValue(v); if (evalOnly) std::cout << v << std::endl; else { -- cgit 1.4.1 From 9a64454faae2ab4ccedeeaad85a0e094726b4765 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 7 Apr 2010 13:59:45 +0000 Subject: * expr-to-xml -> value-to-xml. --- src/libexpr/Makefile.am | 4 +- src/libexpr/expr-to-xml.cc | 149 --------------------------------- src/libexpr/expr-to-xml.hh | 17 ---- src/libexpr/primops.cc | 2 +- src/libexpr/value-to-xml.cc | 149 +++++++++++++++++++++++++++++++++ src/libexpr/value-to-xml.hh | 17 ++++ src/nix-instantiate/nix-instantiate.cc | 11 ++- 7 files changed, 177 insertions(+), 172 deletions(-) delete mode 100644 src/libexpr/expr-to-xml.cc delete mode 100644 src/libexpr/expr-to-xml.hh create mode 100644 src/libexpr/value-to-xml.cc create mode 100644 src/libexpr/value-to-xml.hh (limited to 'src/libexpr/expr-to-xml.cc') diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am index c5f487769b..99f742ffec 100644 --- a/src/libexpr/Makefile.am +++ b/src/libexpr/Makefile.am @@ -2,12 +2,12 @@ pkglib_LTLIBRARIES = libexpr.la libexpr_la_SOURCES = \ nixexpr.cc eval.cc primops.cc lexer-tab.cc parser-tab.cc \ - get-drvs.cc attr-path.cc expr-to-xml.cc common-opts.cc \ + get-drvs.cc attr-path.cc value-to-xml.cc common-opts.cc \ names.cc pkginclude_HEADERS = \ nixexpr.hh eval.hh parser.hh lexer-tab.hh parser-tab.hh \ - get-drvs.hh attr-path.hh expr-to-xml.hh common-opts.hh \ + get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \ names.hh nixexpr-ast.hh libexpr_la_LIBADD = ../libutil/libutil.la ../libstore/libstore.la \ diff --git a/src/libexpr/expr-to-xml.cc b/src/libexpr/expr-to-xml.cc deleted file mode 100644 index ad68739c39..0000000000 --- a/src/libexpr/expr-to-xml.cc +++ /dev/null @@ -1,149 +0,0 @@ -#include "expr-to-xml.hh" -#include "xml-writer.hh" -#include "nixexpr-ast.hh" -#include "aterm.hh" -#include "util.hh" - -#include - - -namespace nix { - - -static XMLAttrs singletonAttrs(const string & name, const string & value) -{ - XMLAttrs attrs; - attrs[name] = value; - return attrs; -} - - -static void printValueAsXML(EvalState & state, bool strict, Value & v, - XMLWriter & doc, PathSet & context, PathSet & drvsSeen); - - -static void showAttrs(EvalState & state, bool strict, Bindings & attrs, - XMLWriter & doc, PathSet & context, PathSet & drvsSeen) -{ - StringSet names; - foreach (Bindings::iterator, i, attrs) - names.insert(aterm2String(i->first)); - foreach (StringSet::iterator, i, names) { - XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); - printValueAsXML(state, strict, attrs[toATerm(*i)], doc, context, drvsSeen); - } -} - - -static void printPatternAsXML(Pattern pat, XMLWriter & doc) -{ - ATerm name; - ATermList formals; - ATermBool ellipsis; - if (matchVarPat(pat, name)) - doc.writeEmptyElement("varpat", singletonAttrs("name", aterm2String(name))); - else if (matchAttrsPat(pat, formals, ellipsis, name)) { - XMLAttrs attrs; - if (name != sNoAlias) attrs["name"] = aterm2String(name); - if (ellipsis == eTrue) attrs["ellipsis"] = "1"; - XMLOpenElement _(doc, "attrspat", attrs); - for (ATermIterator i(formals); i; ++i) { - Expr name; ATerm dummy; - if (!matchFormal(*i, name, dummy)) abort(); - doc.writeEmptyElement("attr", singletonAttrs("name", aterm2String(name))); - } - } -} - - -static void printValueAsXML(EvalState & state, bool strict, Value & v, - XMLWriter & doc, PathSet & context, PathSet & drvsSeen) -{ - checkInterrupt(); - - if (strict) state.forceValue(v); - - switch (v.type) { - - case tInt: - doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str())); - break; - - case tBool: - doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false")); - break; - - case tString: - /* !!! show the context? */ - doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); - break; - - case tPath: - doc.writeEmptyElement("path", singletonAttrs("value", v.path)); - break; - - case tNull: - doc.writeEmptyElement("null"); - break; - - case tAttrs: - if (state.isDerivation(v)) { - XMLAttrs xmlAttrs; - - Bindings::iterator a = v.attrs->find(toATerm("derivation")); - - Path drvPath; - a = v.attrs->find(toATerm("drvPath")); - if (a != v.attrs->end() && a->second.type == tString) - xmlAttrs["drvPath"] = drvPath = a->second.string.s; - - a = v.attrs->find(toATerm("outPath")); - if (a != v.attrs->end() && a->second.type == tString) - xmlAttrs["outPath"] = a->second.string.s; - - XMLOpenElement _(doc, "derivation", xmlAttrs); - - if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { - drvsSeen.insert(drvPath); - showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); - } else - doc.writeEmptyElement("repeated"); - } - - else { - XMLOpenElement _(doc, "attrs"); - showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); - } - - break; - - case tList: { - XMLOpenElement _(doc, "list"); - for (unsigned int n = 0; n < v.list.length; ++n) - printValueAsXML(state, strict, v.list.elems[n], doc, context, drvsSeen); - break; - } - - case tLambda: { - XMLOpenElement _(doc, "function"); - printPatternAsXML(v.lambda.pat, doc); - break; - } - - default: - doc.writeEmptyElement("unevaluated"); - } -} - - -void printValueAsXML(EvalState & state, bool strict, - Value & v, std::ostream & out, PathSet & context) -{ - XMLWriter doc(true, out); - XMLOpenElement root(doc, "expr"); - PathSet drvsSeen; - printValueAsXML(state, strict, v, doc, context, drvsSeen); -} - - -} diff --git a/src/libexpr/expr-to-xml.hh b/src/libexpr/expr-to-xml.hh deleted file mode 100644 index 8f094185c4..0000000000 --- a/src/libexpr/expr-to-xml.hh +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __EXPR_TO_XML_H -#define __EXPR_TO_XML_H - -#include -#include - -#include "nixexpr.hh" -#include "eval.hh" - -namespace nix { - -void printValueAsXML(EvalState & state, bool strict, - Value & v, std::ostream & out, PathSet & context); - -} - -#endif /* !__EXPR_TO_XML_H */ diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 5fa2418b5f..74eb2b26d0 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -4,7 +4,7 @@ #include "store-api.hh" #include "util.hh" #include "archive.hh" -#include "expr-to-xml.hh" +#include "value-to-xml.hh" #include "nixexpr-ast.hh" #include "parser.hh" #include "names.hh" diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc new file mode 100644 index 0000000000..eff414aba3 --- /dev/null +++ b/src/libexpr/value-to-xml.cc @@ -0,0 +1,149 @@ +#include "value-to-xml.hh" +#include "xml-writer.hh" +#include "nixexpr-ast.hh" +#include "aterm.hh" +#include "util.hh" + +#include + + +namespace nix { + + +static XMLAttrs singletonAttrs(const string & name, const string & value) +{ + XMLAttrs attrs; + attrs[name] = value; + return attrs; +} + + +static void printValueAsXML(EvalState & state, bool strict, Value & v, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen); + + +static void showAttrs(EvalState & state, bool strict, Bindings & attrs, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen) +{ + StringSet names; + foreach (Bindings::iterator, i, attrs) + names.insert(aterm2String(i->first)); + foreach (StringSet::iterator, i, names) { + XMLOpenElement _(doc, "attr", singletonAttrs("name", *i)); + printValueAsXML(state, strict, attrs[toATerm(*i)], doc, context, drvsSeen); + } +} + + +static void printPatternAsXML(Pattern pat, XMLWriter & doc) +{ + ATerm name; + ATermList formals; + ATermBool ellipsis; + if (matchVarPat(pat, name)) + doc.writeEmptyElement("varpat", singletonAttrs("name", aterm2String(name))); + else if (matchAttrsPat(pat, formals, ellipsis, name)) { + XMLAttrs attrs; + if (name != sNoAlias) attrs["name"] = aterm2String(name); + if (ellipsis == eTrue) attrs["ellipsis"] = "1"; + XMLOpenElement _(doc, "attrspat", attrs); + for (ATermIterator i(formals); i; ++i) { + Expr name; ATerm dummy; + if (!matchFormal(*i, name, dummy)) abort(); + doc.writeEmptyElement("attr", singletonAttrs("name", aterm2String(name))); + } + } +} + + +static void printValueAsXML(EvalState & state, bool strict, Value & v, + XMLWriter & doc, PathSet & context, PathSet & drvsSeen) +{ + checkInterrupt(); + + if (strict) state.forceValue(v); + + switch (v.type) { + + case tInt: + doc.writeEmptyElement("int", singletonAttrs("value", (format("%1%") % v.integer).str())); + break; + + case tBool: + doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false")); + break; + + case tString: + /* !!! show the context? */ + doc.writeEmptyElement("string", singletonAttrs("value", v.string.s)); + break; + + case tPath: + doc.writeEmptyElement("path", singletonAttrs("value", v.path)); + break; + + case tNull: + doc.writeEmptyElement("null"); + break; + + case tAttrs: + if (state.isDerivation(v)) { + XMLAttrs xmlAttrs; + + Bindings::iterator a = v.attrs->find(toATerm("derivation")); + + Path drvPath; + a = v.attrs->find(toATerm("drvPath")); + if (a != v.attrs->end() && a->second.type == tString) + xmlAttrs["drvPath"] = drvPath = a->second.string.s; + + a = v.attrs->find(toATerm("outPath")); + if (a != v.attrs->end() && a->second.type == tString) + xmlAttrs["outPath"] = a->second.string.s; + + XMLOpenElement _(doc, "derivation", xmlAttrs); + + if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { + drvsSeen.insert(drvPath); + showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); + } else + doc.writeEmptyElement("repeated"); + } + + else { + XMLOpenElement _(doc, "attrs"); + showAttrs(state, strict, *v.attrs, doc, context, drvsSeen); + } + + break; + + case tList: { + XMLOpenElement _(doc, "list"); + for (unsigned int n = 0; n < v.list.length; ++n) + printValueAsXML(state, strict, v.list.elems[n], doc, context, drvsSeen); + break; + } + + case tLambda: { + XMLOpenElement _(doc, "function"); + printPatternAsXML(v.lambda.pat, doc); + break; + } + + default: + doc.writeEmptyElement("unevaluated"); + } +} + + +void printValueAsXML(EvalState & state, bool strict, + Value & v, std::ostream & out, PathSet & context) +{ + XMLWriter doc(true, out); + XMLOpenElement root(doc, "expr"); + PathSet drvsSeen; + printValueAsXML(state, strict, v, doc, context, drvsSeen); +} + + +} diff --git a/src/libexpr/value-to-xml.hh b/src/libexpr/value-to-xml.hh new file mode 100644 index 0000000000..7dfbe06d16 --- /dev/null +++ b/src/libexpr/value-to-xml.hh @@ -0,0 +1,17 @@ +#ifndef __VALUE_TO_XML_H +#define __VALUE_TO_XML_H + +#include +#include + +#include "nixexpr.hh" +#include "eval.hh" + +namespace nix { + +void printValueAsXML(EvalState & state, bool strict, + Value & v, std::ostream & out, PathSet & context); + +} + +#endif /* !__VALUE_TO_XML_H */ diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 2f41fa81b5..ebf1be5b96 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -7,7 +7,7 @@ #include "parser.hh" #include "get-drvs.hh" #include "attr-path.hh" -#include "expr-to-xml.hh" +#include "value-to-xml.hh" #include "util.hh" #include "store-api.hh" #include "common-opts.hh" @@ -75,10 +75,15 @@ void processExpr(EvalState & state, const Strings & attrPaths, std::cout << format("%1%\n") % canonicaliseExpr(e); else { Value v; + PathSet context; state.eval(e, v); - if (strict) state.strictForceValue(v); if (evalOnly) - std::cout << v << std::endl; + if (xmlOutput) + printValueAsXML(state, strict, v, std::cout, context); + else { + if (strict) state.strictForceValue(v); + std::cout << v << std::endl; + } else { DrvInfos drvs; getDerivations(state, v, "", autoArgs, drvs); -- cgit 1.4.1