aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2010-03-30 15:18:20 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2010-03-30 15:18:20 +0000
commitc9170be2bd2e735b37db7e7b4ccaca86835cb5c5 (patch)
treec3351fae157aea73085ec17aebe75decdbf921eb /src/libexpr/eval.cc
parentc3aa615a5f4a8bdde5d836ce91d5daa743ded065 (diff)
* More primops.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc160
1 files changed, 32 insertions, 128 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 06ca01ff4..34c420339 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -405,21 +405,35 @@ void EvalState::eval(Env & env, Expr e, Value & v)
}
if (matchConcatStrings(e, es)) {
- unsigned int n = ATgetLength(es), j = 0;
- Value vs[n];
- unsigned int len = 0;
- for (ATermIterator i(es); i; ++i, ++j) {
- eval(env, *i, vs[j]);
- if (vs[j].type != tString) throw TypeError("string expected");
- len += strlen(vs[j].string.s);
- }
- char * s = new char[len + 1], * t = s;
- for (unsigned int i = 0; i < j; ++i) {
- strcpy(t, vs[i].string.s);
- t += strlen(vs[i].string.s);
+ PathSet context;
+ std::ostringstream s;
+
+ bool first = true, isPath;
+
+ for (ATermIterator i(es); i; ++i) {
+ eval(env, *i, v);
+
+ /* If the first element is a path, then the result will
+ also be a path, we don't copy anything (yet - that's
+ done later, since paths are copied when they are used
+ in a derivation), and none of the strings are allowed
+ to have contexts. */
+ if (first) {
+ isPath = v.type == tPath;
+ first = false;
+ }
+
+ s << coerceToString(v, context, false, !isPath);
}
- *t = 0;
- mkString(v, s);
+
+ if (isPath && !context.empty())
+ throw EvalError(format("a string that refers to a store path cannot be appended to a path, in `%1%'")
+ % s.str());
+
+ if (isPath)
+ mkPath(v, strdup(s.str().c_str()));
+ else
+ mkString(v, strdup(s.str().c_str())); // !!! context
return;
}
@@ -969,116 +983,6 @@ ATermList flattenList(EvalState & state, Expr e)
}
-string coerceToString(EvalState & state, Expr e, PathSet & context,
- bool coerceMore, bool copyToStore)
-{
- e = evalExpr(state, e);
-
- string s;
-
- if (matchStr(e, s, context)) return s;
-
- ATerm s2;
- if (matchPath(e, s2)) {
- Path path(canonPath(aterm2String(s2)));
-
- if (!copyToStore) return path;
-
- if (isDerivation(path))
- throw EvalError(format("file names are not allowed to end in `%1%'")
- % drvExtension);
-
- Path dstPath;
- if (state.srcToStore[path] != "")
- dstPath = state.srcToStore[path];
- else {
- dstPath = readOnlyMode
- ? computeStorePathForPath(path).first
- : store->addToStore(path);
- state.srcToStore[path] = dstPath;
- printMsg(lvlChatty, format("copied source `%1%' -> `%2%'")
- % path % dstPath);
- }
-
- context.insert(dstPath);
- return dstPath;
- }
-
- ATermList es;
- if (matchAttrs(e, es)) {
- Expr e2 = queryAttr(e, "outPath");
- if (!e2) throwTypeError("cannot coerce an attribute set (except a derivation) to a string");
- return coerceToString(state, e2, context, coerceMore, copyToStore);
- }
-
- if (coerceMore) {
-
- /* Note that `false' is represented as an empty string for
- shell scripting convenience, just like `null'. */
- if (e == eTrue) return "1";
- if (e == eFalse) return "";
- int n;
- if (matchInt(e, n)) return int2String(n);
- if (matchNull(e)) return "";
-
- if (matchList(e, es)) {
- string result;
- es = flattenList(state, e);
- bool first = true;
- for (ATermIterator i(es); i; ++i) {
- if (!first) result += " "; else first = false;
- result += coerceToString(state, *i,
- context, coerceMore, copyToStore);
- }
- return result;
- }
- }
-
- throwTypeError("cannot coerce %1% to a string", showType(e));
-}
-
-
-/* Common implementation of `+', ConcatStrings and `~'. */
-static ATerm concatStrings(EvalState & state, ATermVector & args,
- string separator = "")
-{
- if (args.empty()) return makeStr("", PathSet());
-
- PathSet context;
- std::ostringstream s;
-
- /* If the first element is a path, then the result will also be a
- path, we don't copy anything (yet - that's done later, since
- paths are copied when they are used in a derivation), and none
- of the strings are allowed to have contexts. */
- ATerm dummy;
- args.front() = evalExpr(state, args.front());
- bool isPath = matchPath(args.front(), dummy);
-
- for (ATermVector::const_iterator i = args.begin(); i != args.end(); ++i) {
- if (i != args.begin()) s << separator;
- s << coerceToString(state, *i, context, false, !isPath);
- }
-
- if (isPath && !context.empty())
- throw EvalError(format("a string that refers to a store path cannot be appended to a path, in `%1%'")
- % s.str());
-
- return isPath
- ? makePath(toATerm(s.str()))
- : makeStr(s.str(), context);
-}
-
-
-Path coerceToPath(EvalState & state, Expr e, PathSet & context)
-{
- string path = coerceToString(state, e, context, false, false);
- if (path == "" || path[0] != '/')
- throw EvalError(format("string `%1%' doesn't represent an absolute path") % path);
- return path;
-}
-
-
Expr autoCallFunction(Expr e, const ATermMap & args)
{
Pattern pat;
@@ -1515,16 +1419,16 @@ Expr strictEvalExpr(EvalState & state, Expr e)
#endif
-void printEvalStats(EvalState & state)
+void EvalState::printStats()
{
char x;
bool showStats = getEnv("NIX_SHOW_STATS", "0") != "0";
printMsg(showStats ? lvlInfo : lvlDebug,
format("evaluated %1% expressions, used %2% bytes of stack space, allocated %3% values, allocated %4% environments")
- % state.nrEvaluated
+ % nrEvaluated
% (&x - deepestStack)
- % state.nrValues
- % state.nrEnvs);
+ % nrValues
+ % nrEnvs);
if (showStats)
printATermMapStats();
}