From af2a372bb000d4d5aeec37e43ee0f6245c1bba54 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 7 Apr 2010 15:47:06 +0000 Subject: * Update autoCallFunction() and findAlongAttrPath(). --- src/libexpr/attr-path.cc | 54 +++++++++++++++----------------------- src/libexpr/attr-path.hh | 4 +-- src/libexpr/common-opts.cc | 14 +++++----- src/libexpr/common-opts.hh | 2 +- src/libexpr/eval.cc | 64 +++++++++++++++++++++++++++------------------- src/libexpr/eval.hh | 34 +++++------------------- src/libexpr/get-drvs.cc | 9 ++++--- src/libexpr/get-drvs.hh | 2 +- 8 files changed, 81 insertions(+), 102 deletions(-) (limited to 'src/libexpr') diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc index 5d81303fe3d0..5f1c0ad7839d 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 7abaa83a0167..518a7a95da09 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 9e3f8f9614da..d5d3df40a9a9 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 fb9659cdc5a1..80298ce55d1b 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 0d18c552275a..98b6b7bdd150 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 a42b9ebebaba..0ea474447f1f 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 6e651d77f0cf..f5e7242f9f5a 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 733f2020129b..f7d1987ea3b7 100644 --- a/src/libexpr/get-drvs.hh +++ b/src/libexpr/get-drvs.hh @@ -65,7 +65,7 @@ typedef list 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); } -- cgit 1.4.1