* Update autoCallFunction() and findAlongAttrPath().

This commit is contained in:
Eelco Dolstra 2010-04-07 15:47:06 +00:00
parent 9a64454faa
commit af2a372bb0
10 changed files with 120 additions and 188 deletions

View file

@ -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
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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

View file

@ -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
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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,