aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/Makefile.am3
-rw-r--r--src/libexpr/attr-path.cc74
-rw-r--r--src/libexpr/attr-path.hh13
-rw-r--r--src/libexpr/eval.cc22
-rw-r--r--src/libexpr/eval.hh5
-rw-r--r--src/libexpr/get-drvs.cc131
-rw-r--r--src/libexpr/get-drvs.hh4
-rw-r--r--src/nix-env/main.cc12
-rw-r--r--src/nix-instantiate/main.cc25
9 files changed, 170 insertions, 119 deletions
diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am
index 1e77420d5..d59b798c0 100644
--- a/src/libexpr/Makefile.am
+++ b/src/libexpr/Makefile.am
@@ -3,7 +3,8 @@ lib_LTLIBRARIES = libexpr.la
libexpr_la_SOURCES = nixexpr.cc nixexpr.hh parser.cc parser.hh \
eval.cc eval.hh primops.cc \
lexer-tab.c lexer-tab.h parser-tab.c parser-tab.h \
- get-drvs.cc get-drvs.hh
+ get-drvs.cc get-drvs.hh \
+ attr-path.cc attr-path.hh
BUILT_SOURCES = nixexpr-ast.cc nixexpr-ast.hh \
parser-tab.h lexer-tab.h parser-tab.c lexer-tab.c
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
new file mode 100644
index 000000000..274f49cea
--- /dev/null
+++ b/src/libexpr/attr-path.cc
@@ -0,0 +1,74 @@
+#include "attr-path.hh"
+#include "nixexpr-ast.hh"
+
+
+bool isAttrs(EvalState & state, Expr e, ATermMap & attrs)
+{
+ e = evalExpr(state, e);
+ ATermList dummy;
+ if (!matchAttrs(e, dummy)) return false;
+ queryAllAttrs(e, attrs, false);
+ return true;
+}
+
+
+Expr findAlongAttrPath(EvalState & state, const string & attrPath, Expr e)
+{
+ Strings tokens = tokenizeString(attrPath, ".");
+
+ Error attrError =
+ Error(format("attribute selection path `%1%' does not match expression") % attrPath);
+
+ string curPath;
+
+ for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) {
+
+ if (!curPath.empty()) curPath += ".";
+ curPath += *i;
+
+ /* Is *i an index (integer) or a normal attribute name? */
+ enum { apAttr, apIndex } apType = apAttr;
+ string attr = *i;
+ int attrIndex = -1;
+ if (string2Int(attr, attrIndex)) apType = apIndex;
+
+ /* Evaluate the expression. */
+ e = evalExpr(state, autoCallFunction(evalExpr(state, e)));
+
+ /* It should evaluate to either an attribute set or an
+ expression, according to what is specified in the
+ attrPath. */
+
+ if (apType == apAttr) {
+
+ ATermMap attrs(128);
+
+ if (!isAttrs(state, e, attrs))
+ throw TypeError(
+ format("the expression selected by the selection path `%1%' should be an attribute set but is %2%")
+ % curPath % showType(e));
+
+ e = attrs.get(toATerm(attr));
+ if (!e)
+ throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath);
+
+ }
+
+ else if (apType == apIndex) {
+
+ ATermList es;
+ if (!matchList(e, es))
+ throw TypeError(
+ format("the expression selected by the selection path `%1%' should be a list but is %2%")
+ % curPath % showType(e));
+
+ e = ATelementAt(es, attrIndex);
+ if (!e)
+ throw Error(format("list index %1% in selection path `%2%' not found") % attrIndex % curPath);
+
+ }
+
+ }
+
+ return e;
+}
diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh
new file mode 100644
index 000000000..f64ef7a7c
--- /dev/null
+++ b/src/libexpr/attr-path.hh
@@ -0,0 +1,13 @@
+#ifndef __ATTR_PATH_H
+#define __ATTR_PATH_H
+
+#include <string>
+#include <map>
+
+#include "eval.hh"
+
+
+Expr findAlongAttrPath(EvalState & state, const string & attrPath, Expr e);
+
+
+#endif /* !__ATTR_PATH_H */
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index f1a600103..6c78356db 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -287,6 +287,24 @@ static ATerm concatStrings(EvalState & state, const ATermVector & args)
}
+Expr autoCallFunction(Expr e)
+{
+ ATermList formals;
+ ATerm body, pos;
+ if (matchFunction(e, formals, body, pos)) {
+ for (ATermIterator i(formals); i; ++i) {
+ Expr name, def; ATerm values, def2;
+ if (!matchFormal(*i, name, values, def2)) abort();
+ if (!matchDefaultValue(def2, def))
+ throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1%')")
+ % aterm2String(name));
+ }
+ e = makeCall(e, makeAttrs(ATermMap(0)));
+ }
+ return e;
+}
+
+
Expr evalExpr2(EvalState & state, Expr e)
{
Expr e1, e2, e3, e4;
@@ -380,7 +398,9 @@ Expr evalExpr2(EvalState & state, Expr e)
}
}
- else throw TypeError("the left-hand side of the function call is neither a function nor a primop (built-in operation)");
+ else throw TypeError(
+ format("the left-hand side of the function call is neither a function nor a primop (built-in operation) but %1%")
+ % showType(e1));
}
/* Attribute selection. */
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index a3815733e..018c6b726 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -59,6 +59,11 @@ string coerceToStringWithContext(EvalState & state,
ATermList & context, Expr e, bool & isPath);
Expr wrapInContext(ATermList context, Expr e);
+/* Automatically call a function for which each argument has a default
+ value. Note: result is a call, not a normal form; it should be
+ evaluated by calling evalExpr(). */
+Expr autoCallFunction(Expr e);
+
/* Print statistics. */
void printEvalStats(EvalState & state);
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 736c3e522..0afc7bd6d 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -58,7 +58,7 @@ typedef set<Expr> Exprs;
it makes sense for the caller to recursively search for derivations
in `e'. */
static bool getDerivation(EvalState & state, Expr e,
- DrvInfos & drvs, Exprs & doneExprs, string attributeName)
+ const string & attrPath, DrvInfos & drvs, Exprs & doneExprs)
{
try {
@@ -92,7 +92,7 @@ static bool getDerivation(EvalState & state, Expr e,
drv.attrs = attrs;
- drv.attrPath = attributeName;
+ drv.attrPath = attrPath;
drvs.push_back(drv);
return false;
@@ -107,7 +107,7 @@ bool getDerivation(EvalState & state, Expr e, DrvInfo & drv)
{
Exprs doneExprs;
DrvInfos drvs;
- getDerivation(state, e, drvs, doneExprs, "");
+ getDerivation(state, e, "", drvs, doneExprs);
if (drvs.size() != 1) return false;
drv = drvs.front();
return true;
@@ -121,118 +121,53 @@ static string addToPath(const string & s1, const string & s2)
static void getDerivations(EvalState & state, Expr e,
- DrvInfos & drvs, Exprs & doneExprs, const string & attrPath,
- const string & pathTaken)
+ const string & pathPrefix, DrvInfos & drvs, Exprs & doneExprs)
{
- /* Automatically call functions for which each argument has a
- default value. */
- ATermList formals;
- ATerm body, pos;
- if (matchFunction(e, formals, body, pos)) {
- for (ATermIterator i(formals); i; ++i) {
- Expr name, def; ATerm values, def2;
- if (!matchFormal(*i, name, values, def2)) abort();
- if (!matchDefaultValue(def2, def))
- throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1%')")
- % aterm2String(name));
- }
- getDerivations(state,
- makeCall(e, makeAttrs(ATermMap(0))),
- drvs, doneExprs, attrPath, pathTaken);
- return;
- }
-
- /* Parse the start of attrPath. */
- enum { apNone, apAttr, apIndex } apType;
- string attrPathRest;
- string attr;
- int attrIndex;
- Error attrError =
- Error(format("attribute selection path `%1%' does not match expression") % attrPath);
-
- if (attrPath.empty())
- apType = apNone;
- else {
- string::size_type dot = attrPath.find(".");
- if (dot == string::npos) {
- attrPathRest = "";
- attr = attrPath;
- } else {
- attrPathRest = string(attrPath, dot + 1);
- attr = string(attrPath, 0, dot);
- }
- apType = apAttr;
- if (string2Int(attr, attrIndex)) apType = apIndex;
- }
+ e = evalExpr(state, autoCallFunction(evalExpr(state, e)));
/* Process the expression. */
ATermList es;
DrvInfo drv;
- if (!getDerivation(state, e, drvs, doneExprs, pathTaken)) {
- if (apType != apNone) throw attrError;
+ if (!getDerivation(state, e, pathPrefix, drvs, doneExprs))
return;
- }
-
- e = evalExpr(state, e);
if (matchAttrs(e, es)) {
- if (apType != apNone && apType != apAttr) throw attrError;
ATermMap drvMap(ATgetLength(es));
queryAllAttrs(e, drvMap);
- if (apType == apNone) {
- for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
- startNest(nest, lvlDebug,
- format("evaluating attribute `%1%'") % aterm2String(i->key));
- string pathTaken2 = addToPath(pathTaken, aterm2String(i->key));
- if (getDerivation(state, i->value, drvs, doneExprs, pathTaken2)) {
- /* If the value of this attribute is itself an
- attribute set, should we recurse into it?
- => Only if it has a `recurseForDerivations = true'
- attribute. */
- ATermList es;
- Expr e = evalExpr(state, i->value);
- if (matchAttrs(e, es)) {
- ATermMap attrs(ATgetLength(es));
- queryAllAttrs(e, attrs, false);
- Expr e2 = attrs.get(toATerm("recurseForDerivations"));
- if (e2 && evalBool(state, e2))
- getDerivations(state, e, drvs, doneExprs, attrPathRest, pathTaken2);
- }
+
+ for (ATermMap::const_iterator i = drvMap.begin(); i != drvMap.end(); ++i) {
+ startNest(nest, lvlDebug,
+ format("evaluating attribute `%1%'") % aterm2String(i->key));
+ string pathPrefix2 = addToPath(pathPrefix, aterm2String(i->key));
+ if (getDerivation(state, i->value, pathPrefix2, drvs, doneExprs)) {
+ /* If the value of this attribute is itself an
+ attribute set, should we recurse into it? => Only
+ if it has a `recurseForDerivations = true'
+ attribute. */
+ ATermList es;
+ Expr e = evalExpr(state, i->value);
+ if (matchAttrs(e, es)) {
+ ATermMap attrs(ATgetLength(es));
+ queryAllAttrs(e, attrs, false);
+ Expr e2 = attrs.get(toATerm("recurseForDerivations"));
+ if (e2 && evalBool(state, e2))
+ getDerivations(state, e, pathPrefix2, drvs, doneExprs);
}
}
- } else {
- Expr e2 = drvMap.get(toATerm(attr));
- if (!e2) throw Error(format("attribute `%1%' in selection path not found") % attr);
- startNest(nest, lvlDebug,
- format("evaluating attribute `%1%'") % attr);
- string pathTaken2 = addToPath(pathTaken, attr);
- getDerivation(state, e2, drvs, doneExprs, pathTaken2);
- if (!attrPath.empty())
- getDerivations(state, e2, drvs, doneExprs, attrPathRest, pathTaken2);
}
+
return;
}
if (matchList(e, es)) {
- if (apType != apNone && apType != apIndex) throw attrError;
- if (apType == apNone) {
- int n = 0;
- for (ATermIterator i(es); i; ++i, ++n) {
- startNest(nest, lvlDebug,
- format("evaluating list element"));
- string pathTaken2 = addToPath(pathTaken, (format("%1%") % n).str());
- if (getDerivation(state, *i, drvs, doneExprs, pathTaken2))
- getDerivations(state, *i, drvs, doneExprs, attrPathRest, pathTaken2);
- }
- } else {
- Expr e2 = ATelementAt(es, attrIndex);
- if (!e2) throw Error(format("list index %1% in selection path not found") % attrIndex);
+ int n = 0;
+ for (ATermIterator i(es); i; ++i, ++n) {
startNest(nest, lvlDebug,
format("evaluating list element"));
- string pathTaken2 = addToPath(pathTaken, (format("%1%") % attrIndex).str());
- if (getDerivation(state, e2, drvs, doneExprs, pathTaken2))
- getDerivations(state, e2, drvs, doneExprs, attrPathRest, pathTaken2);
+ string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
+ if (getDerivation(state, *i, pathPrefix2, drvs, doneExprs))
+ getDerivations(state, *i, pathPrefix2, drvs, doneExprs);
}
return;
}
@@ -241,9 +176,9 @@ static void getDerivations(EvalState & state, Expr e,
}
-void getDerivations(EvalState & state, Expr e, DrvInfos & drvs,
- const string & attrPath)
+void getDerivations(EvalState & state, Expr e, const string & pathPrefix,
+ DrvInfos & drvs)
{
Exprs doneExprs;
- getDerivations(state, e, drvs, doneExprs, attrPath, "");
+ getDerivations(state, e, pathPrefix, drvs, doneExprs);
}
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index 4fb8f43fe..84ffe25ca 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -49,8 +49,8 @@ typedef list<DrvInfo> DrvInfos;
Otherwise, return false. */
bool getDerivation(EvalState & state, Expr e, DrvInfo & drv);
-void getDerivations(EvalState & state, Expr e, DrvInfos & drvs,
- const string & attrPath = "");
+void getDerivations(EvalState & state, Expr e, const string & pathPrefix,
+ DrvInfos & drvs);
#endif /* !__GET_DRVS_H */
diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc
index 875cdd744..3fcaaff42 100644
--- a/src/nix-env/main.cc
+++ b/src/nix-env/main.cc
@@ -10,6 +10,7 @@
#include "help.txt.hh"
#include "nixexpr-ast.hh"
#include "get-drvs.hh"
+#include "attr-path.hh"
#include "pathlocks.hh"
#include <cerrno>
@@ -36,7 +37,6 @@ struct InstallSourceInfo
Path nixExprPath; /* for srcNixExprDrvs, srcNixExprs */
Path profile; /* for srcProfile */
string systemFilter; /* for srcNixExprDrvs */
- string attrPath; /* srcAttrPath */
};
@@ -65,7 +65,7 @@ static void loadDerivations(EvalState & state, Path nixExprPath,
string systemFilter, DrvInfos & elems)
{
getDerivations(state,
- parseExprFromFile(state, absPath(nixExprPath)), elems);
+ parseExprFromFile(state, absPath(nixExprPath)), "", elems);
/* Filter out all derivations not applicable to the current
system. */
@@ -119,7 +119,7 @@ static DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
e = bottomupRewrite(addPos, e);
DrvInfos elems;
- getDerivations(state, e, elems);
+ getDerivations(state, e, "", elems);
return elems;
}
@@ -334,7 +334,7 @@ static void queryInstSources(EvalState & state,
{
Expr e2 = parseExprFromString(state, *i, absPath("."));
Expr call = makeCall(e2, e1);
- getDerivations(state, call, elems);
+ getDerivations(state, call, "", elems);
}
break;
@@ -388,7 +388,9 @@ static void queryInstSources(EvalState & state,
for (Strings::const_iterator i = args.begin();
i != args.end(); ++i)
getDerivations(state,
- parseExprFromFile(state, instSource.nixExprPath), elems, *i);
+ findAlongAttrPath(state, *i,
+ parseExprFromFile(state, instSource.nixExprPath)),
+ "", elems);
break;
}
}
diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc
index 31d61f3af..963e81bac 100644
--- a/src/nix-instantiate/main.cc
+++ b/src/nix-instantiate/main.cc
@@ -9,6 +9,7 @@
#include "parser.hh"
#include "nixexpr-ast.hh"
#include "get-drvs.hh"
+#include "attr-path.hh"
#include "help.txt.hh"
@@ -18,13 +19,12 @@ void printHelp()
}
-static Expr evalStdin(EvalState & state, bool parseOnly)
+static Expr parseStdin(EvalState & state)
{
- startNest(nest, lvlTalkative, format("evaluating standard input"));
+ startNest(nest, lvlTalkative, format("parsing standard input"));
string s, s2;
while (getline(cin, s2)) s += s2 + "\n";
- Expr e = parseExprFromString(state, s, absPath("."));
- return parseOnly ? e : evalExpr(state, e);
+ return parseExprFromString(state, s, absPath("."));
}
@@ -34,7 +34,7 @@ static bool indirectRoot = false;
static void printResult(EvalState & state, Expr e,
- bool evalOnly, bool printArgs, const string & attrPath)
+ bool evalOnly, bool printArgs)
{
if (evalOnly)
cout << format("%1%\n") % e;
@@ -54,7 +54,7 @@ static void printResult(EvalState & state, Expr e,
else {
DrvInfos drvs;
- getDerivations(state, e, drvs, attrPath);
+ getDerivations(state, e, "", drvs);
for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) {
Path drvPath = i->queryDrvPath(state);
if (gcRoot == "")
@@ -119,18 +119,19 @@ void run(Strings args)
openDB();
if (readStdin) {
- Expr e = evalStdin(state, parseOnly);
- printResult(state, e, evalOnly, printArgs, attrPath);
+ Expr e = findAlongAttrPath(state, attrPath, parseStdin(state));
+ if (!parseOnly) e = evalExpr(state, e);
+ printResult(state, e, evalOnly, printArgs);
}
for (Strings::iterator i = files.begin();
i != files.end(); i++)
{
Path path = absPath(*i);
- Expr e = parseOnly
- ? parseExprFromFile(state, path)
- : evalFile(state, path);
- printResult(state, e, evalOnly, printArgs, attrPath);
+ Expr e = findAlongAttrPath(state, attrPath,
+ parseExprFromFile(state, path));
+ if (!parseOnly) e = evalExpr(state, e);
+ printResult(state, e, evalOnly, printArgs);
}
printEvalStats(state);