1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-27 12:41:15 +02:00

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