forked from lix-project/lix
* Update autoCallFunction() and findAlongAttrPath().
This commit is contained in:
parent
9a64454faa
commit
af2a372bb0
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue