aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/attr-path.cc54
-rw-r--r--src/libexpr/attr-path.hh4
-rw-r--r--src/libexpr/common-opts.cc14
-rw-r--r--src/libexpr/common-opts.hh2
-rw-r--r--src/libexpr/eval.cc64
-rw-r--r--src/libexpr/eval.hh34
-rw-r--r--src/libexpr/get-drvs.cc9
-rw-r--r--src/libexpr/get-drvs.hh2
-rw-r--r--src/nix-env/nix-env.cc22
-rw-r--r--src/nix-instantiate/nix-instantiate.cc103
10 files changed, 120 insertions, 188 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index 5d81303fe..5f1c0ad78 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -6,19 +6,8 @@
namespace nix {
-#if 0
-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,
- const ATermMap & autoArgs, Expr e)
+void findAlongAttrPath(EvalState & state, const string & attrPath,
+ const Bindings & autoArgs, Expr e, Value & v)
{
Strings tokens = tokenizeString(attrPath, ".");
@@ -26,8 +15,10 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath,
Error(format("attribute selection path `%1%' does not match expression") % attrPath);
string curPath;
+
+ state.mkThunk_(v, e);
- for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) {
+ foreach (Strings::iterator, i, tokens) {
if (!curPath.empty()) curPath += ".";
curPath += *i;
@@ -39,7 +30,10 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath,
if (string2Int(attr, attrIndex)) apType = apIndex;
/* Evaluate the expression. */
- e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs));
+ Value vTmp;
+ state.autoCallFunction(autoArgs, v, vTmp);
+ v = vTmp;
+ state.forceValue(v);
/* It should evaluate to either an attribute set or an
expression, according to what is specified in the
@@ -47,38 +41,32 @@ Expr findAlongAttrPath(EvalState & state, const string & attrPath,
if (apType == apAttr) {
- ATermMap attrs;
-
- if (!isAttrs(state, e, attrs))
+ if (v.type != tAttrs)
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);
+ % curPath % showType(v));
+ Bindings::iterator a = v.attrs->find(toATerm(attr));
+ if (a == v.attrs->end())
+ throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath);
+ v = a->second;
}
else if (apType == apIndex) {
- ATermList es;
- if (!matchList(e, es))
+ if (v.type != tList)
throw TypeError(
format("the expression selected by the selection path `%1%' should be a list but is %2%")
- % curPath % showType(e));
+ % curPath % showType(v));
- e = ATelementAt(es, attrIndex);
- if (!e)
- throw Error(format("list index %1% in selection path `%2%' not found") % attrIndex % curPath);
-
+ if (attrIndex >= v.list.length)
+ throw Error(format("list index %1% in selection path `%2%' is out of range") % attrIndex % curPath);
+
+ v = v.list.elems[attrIndex];
}
}
-
- return e;
}
-#endif
}
diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh
index 7abaa83a0..518a7a95d 100644
--- a/src/libexpr/attr-path.hh
+++ b/src/libexpr/attr-path.hh
@@ -10,8 +10,8 @@
namespace nix {
-Expr findAlongAttrPath(EvalState & state, const string & attrPath,
- const ATermMap & autoArgs, Expr e);
+void findAlongAttrPath(EvalState & state, const string & attrPath,
+ const Bindings & autoArgs, Expr e, Value & v);
}
diff --git a/src/libexpr/common-opts.cc b/src/libexpr/common-opts.cc
index 9e3f8f961..d5d3df40a 100644
--- a/src/libexpr/common-opts.cc
+++ b/src/libexpr/common-opts.cc
@@ -9,7 +9,7 @@ namespace nix {
bool parseOptionArg(const string & arg, Strings::iterator & i,
const Strings::iterator & argsEnd, EvalState & state,
- ATermMap & autoArgs)
+ Bindings & autoArgs)
{
if (arg != "--arg" && arg != "--argstr") return false;
@@ -19,11 +19,13 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
string name = *i++;
if (i == argsEnd) throw error;
string value = *i++;
-
- Expr e = arg == "--arg"
- ? parseExprFromString(state, value, absPath("."))
- : makeStr(value);
- autoArgs.set(toATerm(name), e);
+
+ Value & v(autoArgs[toATerm(name)]);
+
+ if (arg == "--arg")
+ state.mkThunk_(v, parseExprFromString(state, value, absPath(".")));
+ else
+ mkString(v, value);
return true;
}
diff --git a/src/libexpr/common-opts.hh b/src/libexpr/common-opts.hh
index fb9659cdc..80298ce55 100644
--- a/src/libexpr/common-opts.hh
+++ b/src/libexpr/common-opts.hh
@@ -9,7 +9,7 @@ namespace nix {
/* Some common option parsing between nix-env and nix-instantiate. */
bool parseOptionArg(const string & arg, Strings::iterator & i,
const Strings::iterator & argsEnd, EvalState & state,
- ATermMap & autoArgs);
+ Bindings & autoArgs);
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 0d18c5522..98b6b7bdd 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -260,6 +260,12 @@ void EvalState::mkAttrs(Value & v)
}
+void EvalState::mkThunk_(Value & v, Expr expr)
+{
+ mkThunk(v, baseEnv, expr);
+}
+
+
void EvalState::cloneAttrs(Value & src, Value & dst)
{
mkAttrs(dst);
@@ -625,6 +631,37 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
}
+void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res)
+{
+ forceValue(fun);
+
+ ATerm name;
+ ATermList formals;
+ ATermBool ellipsis;
+
+ if (fun.type != tLambda || !matchAttrsPat(fun.lambda.pat, formals, ellipsis, name)) {
+ res = fun;
+ return;
+ }
+
+ Value actualArgs;
+ mkAttrs(actualArgs);
+
+ for (ATermIterator i(formals); i; ++i) {
+ Expr name, def; ATerm def2;
+ if (!matchFormal(*i, name, def2)) abort();
+ Bindings::const_iterator j = args.find(name);
+ if (j != args.end())
+ (*actualArgs.attrs)[name] = j->second;
+ else if (!matchDefaultValue(def2, def))
+ throw TypeError(format("cannot auto-call a function that has an argument without a default value (`%1% ')")
+ % aterm2String(name));
+ }
+
+ callFunction(fun, actualArgs, res);
+}
+
+
void EvalState::eval(Expr e, Value & v)
{
eval(baseEnv, e, v);
@@ -1058,33 +1095,6 @@ ATermList flattenList(EvalState & state, Expr e)
}
-Expr autoCallFunction(Expr e, const ATermMap & args)
-{
- Pattern pat;
- ATerm body, pos, name;
- ATermList formals;
- ATermBool ellipsis;
-
- if (matchFunction(e, pat, body, pos) && matchAttrsPat(pat, formals, ellipsis, name)) {
- ATermMap actualArgs(ATgetLength(formals));
-
- for (ATermIterator i(formals); i; ++i) {
- Expr name, def, value; ATerm def2;
- if (!matchFormal(*i, name, def2)) abort();
- if ((value = args.get(name)))
- actualArgs.set(name, makeAttrRHS(value, makeNoPos()));
- else 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(actualArgs));
- }
-
- return e;
-}
-
-
/* Evaluation of various language constructs. These have been taken
out of evalExpr2 to reduce stack space usage. (GCC is really dumb
about stack space: it just adds up all the local variables and
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index a42b9ebeb..0ea474447 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -226,13 +226,18 @@ public:
void callFunction(Value & fun, Value & arg, Value & v);
+ /* Automatically call a function for which each argument has a
+ default value or has a binding in the `args' map. */
+ void autoCallFunction(const Bindings & args, Value & fun, Value & res);
+
/* Allocation primitives. */
Value * allocValues(unsigned int count);
Env & allocEnv();
void mkList(Value & v, unsigned int length);
void mkAttrs(Value & v);
-
+ void mkThunk_(Value & v, Expr expr);
+
void cloneAttrs(Value & src, Value & dst);
/* Print statistics. */
@@ -244,33 +249,6 @@ public:
string showType(Value & v);
-#if 0
-/* Evaluate an expression to normal form. */
-Expr evalExpr(EvalState & state, Expr e);
-
-/* Evaluate an expression, and recursively evaluate list elements and
- attributes. If `canonicalise' is true, we remove things like
- position information and make sure that attribute sets are in
- sorded order. */
-Expr strictEvalExpr(EvalState & state, Expr e);
-
-/* Specific results. */
-string evalString(EvalState & state, Expr e, PathSet & context);
-int evalInt(EvalState & state, Expr e);
-bool evalBool(EvalState & state, Expr e);
-ATermList evalList(EvalState & state, Expr e);
-
-/* Flatten nested lists into a single list (or expand a singleton into
- a list). */
-ATermList flattenList(EvalState & state, Expr e);
-
-/* Automatically call a function for which each argument has a default
- value or has a binding in the `args' map. Note: result is a call,
- not a normal form; it should be evaluated by calling evalExpr(). */
-Expr autoCallFunction(Expr e, const ATermMap & args);
-#endif
-
-
}
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 6e651d77f..f5e7242f9 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -155,11 +155,12 @@ static string addToPath(const string & s1, const string & s2)
}
-static void getDerivations(EvalState & state, Value & v,
- const string & pathPrefix, const ATermMap & autoArgs,
+static void getDerivations(EvalState & state, Value & vIn,
+ const string & pathPrefix, const Bindings & autoArgs,
DrvInfos & drvs, Done & done)
{
- // !!! autoCallFunction(evalExpr(state, e), autoArgs)
+ Value v;
+ state.autoCallFunction(autoArgs, vIn, v);
/* Process the expression. */
DrvInfo drv;
@@ -216,7 +217,7 @@ static void getDerivations(EvalState & state, Value & v,
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
- const ATermMap & autoArgs, DrvInfos & drvs)
+ const Bindings & autoArgs, DrvInfos & drvs)
{
Done done;
getDerivations(state, v, pathPrefix, autoArgs, drvs, done);
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index 733f20201..f7d1987ea 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -65,7 +65,7 @@ typedef list<DrvInfo> DrvInfos;
bool getDerivation(EvalState & state, Value & v, DrvInfo & drv);
void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
- const ATermMap & autoArgs, DrvInfos & drvs);
+ const Bindings & autoArgs, DrvInfos & drvs);
}
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index ea85656a2..20affa83d 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -47,7 +47,7 @@ struct InstallSourceInfo
Path profile; /* for srcProfile */
string systemFilter; /* for srcNixExprDrvs */
bool prebuiltOnly;
- ATermMap autoArgs;
+ Bindings autoArgs;
InstallSourceInfo() : prebuiltOnly(false) { };
};
@@ -161,13 +161,11 @@ static Expr loadSourceExpr(EvalState & state, const Path & path)
static void loadDerivations(EvalState & state, Path nixExprPath,
- string systemFilter, const ATermMap & autoArgs,
+ string systemFilter, const Bindings & autoArgs,
const string & pathPrefix, DrvInfos & elems)
{
Value v;
- state.eval(loadSourceExpr(state, nixExprPath), v);
-
- // !!! findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath))
+ findAlongAttrPath(state, pathPrefix, autoArgs, loadSourceExpr(state, nixExprPath), v);
getDerivations(state, v, pathPrefix, autoArgs, elems);
@@ -579,14 +577,12 @@ static void queryInstSources(EvalState & state,
}
case srcAttrPath: {
- throw Error("not implemented");
-#if 0
- foreach (Strings::const_iterator, i, args)
- getDerivations(state,
- findAlongAttrPath(state, *i, instSource.autoArgs,
- loadSourceExpr(state, instSource.nixExprPath)),
- "", instSource.autoArgs, elems);
-#endif
+ foreach (Strings::const_iterator, i, args) {
+ Value v;
+ findAlongAttrPath(state, *i, instSource.autoArgs,
+ loadSourceExpr(state, instSource.nixExprPath), v);
+ getDerivations(state, v, "", instSource.autoArgs, elems);
+ }
break;
}
}
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index ebf1be5b9..ac405aa66 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -37,80 +37,41 @@ static int rootNr = 0;
static bool indirectRoot = false;
-#if 0
-static void printResult(EvalState & state, Expr e,
- bool evalOnly, bool xmlOutput, const ATermMap & autoArgs)
-{
- PathSet context;
-
- if (evalOnly)
- if (xmlOutput)
- printTermAsXML(e, std::cout, context);
- else
- std::cout << format("%1%\n") % canonicaliseExpr(e);
-
- else {
- DrvInfos drvs;
- getDerivations(state, e, "", autoArgs, drvs);
- for (DrvInfos::iterator i = drvs.begin(); i != drvs.end(); ++i) {
- Path drvPath = i->queryDrvPath(state);
- if (gcRoot == "")
- printGCWarning();
- else
- drvPath = addPermRoot(drvPath,
- makeRootName(gcRoot, rootNr),
- indirectRoot);
- std::cout << format("%1%\n") % drvPath;
- }
- }
-}
-#endif
-
-
void processExpr(EvalState & state, const Strings & attrPaths,
- bool parseOnly, bool strict, const ATermMap & autoArgs,
+ bool parseOnly, bool strict, const Bindings & autoArgs,
bool evalOnly, bool xmlOutput, Expr e)
{
if (parseOnly)
std::cout << format("%1%\n") % canonicaliseExpr(e);
- else {
- Value v;
- PathSet context;
- state.eval(e, v);
- if (evalOnly)
- if (xmlOutput)
- printValueAsXML(state, strict, v, std::cout, context);
+ else
+ foreach (Strings::const_iterator, i, attrPaths) {
+ Value v;
+ findAlongAttrPath(state, *i, autoArgs, e, v);
+ state.forceValue(v);
+
+ PathSet context;
+ if (evalOnly)
+ if (xmlOutput)
+ printValueAsXML(state, strict, v, std::cout, context);
+ else {
+ if (strict) state.strictForceValue(v);
+ std::cout << v << std::endl;
+ }
else {
- if (strict) state.strictForceValue(v);
- std::cout << v << std::endl;
- }
- else {
- DrvInfos drvs;
- getDerivations(state, v, "", autoArgs, drvs);
- foreach (DrvInfos::iterator, i, drvs) {
- Path drvPath = i->queryDrvPath(state);
- if (gcRoot == "")
- printGCWarning();
- else
- drvPath = addPermRoot(drvPath,
- makeRootName(gcRoot, rootNr),
- indirectRoot);
- std::cout << format("%1%\n") % drvPath;
+ DrvInfos drvs;
+ getDerivations(state, v, "", autoArgs, drvs);
+ foreach (DrvInfos::iterator, i, drvs) {
+ Path drvPath = i->queryDrvPath(state);
+ if (gcRoot == "")
+ printGCWarning();
+ else
+ drvPath = addPermRoot(drvPath,
+ makeRootName(gcRoot, rootNr),
+ indirectRoot);
+ std::cout << format("%1%\n") % drvPath;
+ }
}
}
- }
-
-#if 0
- for (Strings::const_iterator i = attrPaths.begin(); i != attrPaths.end(); ++i) {
- Expr e2 = findAlongAttrPath(state, *i, autoArgs, e);
- if (!parseOnly)
- if (strict)
- e2 = state.strictEval(e2);
- else
- e2 = evalExpr(state, e2);
- printResult(state, e2, evalOnly, xmlOutput, autoArgs);
- }
-#endif
}
@@ -124,11 +85,9 @@ void run(Strings args)
bool xmlOutput = false;
bool strict = false;
Strings attrPaths;
- ATermMap autoArgs(128);
+ Bindings autoArgs;
- for (Strings::iterator i = args.begin();
- i != args.end(); )
- {
+ for (Strings::iterator i = args.begin(); i != args.end(); ) {
string arg = *i++;
if (arg == "-")
@@ -175,9 +134,7 @@ void run(Strings args)
evalOnly, xmlOutput, e);
}
- for (Strings::iterator i = files.begin();
- i != files.end(); i++)
- {
+ foreach (Strings::iterator, i, files) {
Path path = absPath(*i);
Expr e = parseExprFromFile(state, path);
processExpr(state, attrPaths, parseOnly, strict, autoArgs,