aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libexpr/attr-path.cc2
-rw-r--r--src/libexpr/eval-test.cc1
-rw-r--r--src/libexpr/eval.cc33
-rw-r--r--src/libexpr/eval.hh4
-rw-r--r--src/libexpr/get-drvs.cc6
-rw-r--r--src/libexpr/primops.cc27
-rw-r--r--src/libexpr/value-to-xml.cc2
7 files changed, 41 insertions, 34 deletions
diff --git a/src/libexpr/attr-path.cc b/src/libexpr/attr-path.cc
index b53837781..769acb6b8 100644
--- a/src/libexpr/attr-path.cc
+++ b/src/libexpr/attr-path.cc
@@ -61,7 +61,7 @@ void findAlongAttrPath(EvalState & state, const string & attrPath,
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];
+ v = *v.list.elems[attrIndex];
}
}
diff --git a/src/libexpr/eval-test.cc b/src/libexpr/eval-test.cc
index a7786561e..f7f91f503 100644
--- a/src/libexpr/eval-test.cc
+++ b/src/libexpr/eval-test.cc
@@ -113,6 +113,7 @@ void run(Strings args)
doTest(state, "with { x = 1; }; let inherit x; y = x; in y");
doTest(state, "builtins.toXML 123");
doTest(state, "builtins.toXML { a.b = \"x\" + \"y\"; c = [ 1 2 ] ++ [ 3 4 ]; }");
+ doTest(state, "builtins.attrNames { x = 1; y = 2; }");
state.printStats();
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index d6e39f365..69e7bd8b3 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -50,7 +50,7 @@ std::ostream & operator << (std::ostream & str, Value & v)
case tList:
str << "[ ";
for (unsigned int n = 0; n < v.list.length; ++n)
- str << v.list.elems[n] << " ";
+ str << *v.list.elems[n] << " ";
str << "]";
break;
case tThunk:
@@ -102,7 +102,7 @@ EvalState::EvalState()
, baseEnvDispl(0)
, staticBaseEnv(false, 0)
{
- nrEnvs = nrValuesInEnvs = nrValuesInLists = nrValues = 0;
+ nrEnvs = nrValuesInEnvs = nrValues = nrListElems = 0;
nrEvaluated = recursionDepth = maxRecursionDepth = 0;
deepestStack = (char *) -1;
@@ -251,6 +251,7 @@ Value * EvalState::lookupVar(Env * env, const VarRef & var)
Value * EvalState::allocValues(unsigned int count)
{
+ nrValues += count;
return new Value[count]; // !!! check destructor
}
@@ -268,8 +269,8 @@ void EvalState::mkList(Value & v, unsigned int length)
{
v.type = tList;
v.list.length = length;
- v.list.elems = allocValues(length);
- nrValuesInLists += length;
+ v.list.elems = new Value *[length];
+ nrListElems += length;
}
@@ -461,8 +462,11 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
void ExprList::eval(EvalState & state, Env & env, Value & v)
{
state.mkList(v, elems.size());
- for (unsigned int n = 0; n < v.list.length; ++n)
- mkThunk(v.list.elems[n], env, elems[n]);
+ Value * vs = state.allocValues(v.list.length);
+ for (unsigned int n = 0; n < v.list.length; ++n) {
+ v.list.elems[n] = &vs[n];
+ mkThunk(vs[n], env, elems[n]);
+ }
}
@@ -543,7 +547,6 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
primOp->primOp.fun(*this, vArgs, v);
} else {
Value * v2 = allocValues(2);
- nrValues += 2;
v2[0] = fun;
v2[1] = arg;
v.type = tPrimOpApp;
@@ -734,8 +737,6 @@ void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
Value v2; state.eval(env, e2, v2);
state.forceList(v2);
state.mkList(v, v1.list.length + v2.list.length);
- /* !!! This loses sharing with the original lists. We could use a
- tCopy node, but that would use more memory. */
for (unsigned int n = 0; n < v1.list.length; ++n)
v.list.elems[n] = v1.list.elems[n];
for (unsigned int n = 0; n < v2.list.length; ++n)
@@ -810,7 +811,7 @@ void EvalState::strictForceValue(Value & v)
else if (v.type == tList) {
for (unsigned int n = 0; n < v.list.length; ++n)
- strictForceValue(v.list.elems[n]);
+ strictForceValue(*v.list.elems[n]);
}
}
@@ -951,11 +952,11 @@ string EvalState::coerceToString(Value & v, PathSet & context,
if (v.type == tList) {
string result;
for (unsigned int n = 0; n < v.list.length; ++n) {
- result += coerceToString(v.list.elems[n],
+ result += coerceToString(*v.list.elems[n],
context, coerceMore, copyToStore);
if (n < v.list.length - 1
/* !!! not quite correct */
- && (v.list.elems[n].type != tList || v.list.elems[n].list.length != 0))
+ && (v.list.elems[n]->type != tList || v.list.elems[n]->list.length != 0))
result += " ";
}
return result;
@@ -1009,14 +1010,14 @@ bool EvalState::eqValues(Value & v1, Value & v2)
case tList:
if (v2.type != tList || v1.list.length != v2.list.length) return false;
for (unsigned int n = 0; n < v1.list.length; ++n)
- if (!eqValues(v1.list.elems[n], v2.list.elems[n])) return false;
+ if (!eqValues(*v1.list.elems[n], *v2.list.elems[n])) return false;
return true;
case tAttrs: {
if (v2.type != tAttrs || v1.attrs->size() != v2.attrs->size()) return false;
Bindings::iterator i, j;
for (i = v1.attrs->begin(), j = v2.attrs->begin(); i != v1.attrs->end(); ++i, ++j)
- if (!eqValues(i->second, j->second)) return false;
+ if (i->first != j->first || !eqValues(i->second, j->second)) return false;
return true;
}
@@ -1046,8 +1047,8 @@ void EvalState::printStats()
% nrEnvs % (nrEnvs * sizeof(Env)));
printMsg(v, format(" values allocated in environments: %1% (%2% bytes)")
% nrValuesInEnvs % (nrValuesInEnvs * sizeof(Value)));
- printMsg(v, format(" values allocated in lists: %1% (%2% bytes)")
- % nrValuesInLists % (nrValuesInLists * sizeof(Value)));
+ printMsg(v, format(" list elements: %1% (%2% bytes)")
+ % nrListElems % (nrListElems * sizeof(Value *)));
printMsg(v, format(" misc. values allocated: %1% (%2% bytes) ")
% nrValues % (nrValues * sizeof(Value)));
printMsg(v, format(" symbols in symbol table: %1%") % symbols.size());
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 313a1d9b8..7252cae4b 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -76,7 +76,7 @@ struct Value
Bindings * attrs;
struct {
unsigned int length;
- Value * elems;
+ Value * * elems;
} list;
struct {
Env * env;
@@ -282,8 +282,8 @@ private:
unsigned long nrEnvs;
unsigned long nrValuesInEnvs;
- unsigned long nrValuesInLists;
unsigned long nrValues;
+ unsigned long nrListElems;
unsigned long nrEvaluated;
unsigned int recursionDepth;
unsigned int maxRecursionDepth;
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 399470192..6964e3e3b 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -48,7 +48,7 @@ MetaInfo DrvInfo::queryMetaInfo(EvalState & state) const
} else if (i->second.type == tList) {
value.type = MetaValue::tpStrings;
for (unsigned int j = 0; j < i->second.list.length; ++j)
- value.stringValues.push_back(state.forceStringNoCtx(i->second.list.elems[j]));
+ value.stringValues.push_back(state.forceStringNoCtx(*i->second.list.elems[j]));
} else continue;
meta[i->first] = value;
}
@@ -206,8 +206,8 @@ static void getDerivations(EvalState & state, Value & vIn,
startNest(nest, lvlDebug,
format("evaluating list element"));
string pathPrefix2 = addToPath(pathPrefix, (format("%1%") % n).str());
- if (getDerivation(state, v.list.elems[n], pathPrefix2, drvs, done))
- getDerivations(state, v.list.elems[n], pathPrefix2, autoArgs, drvs, done);
+ if (getDerivation(state, *v.list.elems[n], pathPrefix2, drvs, done))
+ getDerivations(state, *v.list.elems[n], pathPrefix2, autoArgs, drvs, done);
}
}
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 0d7459fee..ae17506ce 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -311,7 +311,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
if (key == "args") {
state.forceList(i->second);
for (unsigned int n = 0; n < i->second.list.length; ++n) {
- string s = state.coerceToString(i->second.list.elems[n], context, true);
+ string s = state.coerceToString(*i->second.list.elems[n], context, true);
drv.args.push_back(s);
}
}
@@ -651,14 +651,17 @@ static void prim_attrNames(EvalState & state, Value * * args, Value & v)
state.forceAttrs(*args[0]);
state.mkList(v, args[0]->attrs->size());
+ Value * vs = state.allocValues(v.list.length);
StringSet names;
foreach (Bindings::iterator, i, *args[0]->attrs)
names.insert(i->first);
unsigned int n = 0;
- foreach (StringSet::iterator, i, names)
- mkString(v.list.elems[n++], *i);
+ foreach (StringSet::iterator, i, names) {
+ v.list.elems[n] = &vs[n];
+ mkString(vs[n++], *i);
+ }
}
@@ -701,8 +704,8 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
state.cloneAttrs(*args[0], v);
for (unsigned int i = 0; i < args[1]->list.length; ++i) {
- state.forceStringNoCtx(args[1]->list.elems[i]);
- v.attrs->erase(state.symbols.create(args[1]->list.elems[i].string.s));
+ state.forceStringNoCtx(*args[1]->list.elems[i]);
+ v.attrs->erase(state.symbols.create(args[1]->list.elems[i]->string.s));
}
}
@@ -718,7 +721,7 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
state.mkAttrs(v);
for (unsigned int i = 0; i < args[0]->list.length; ++i) {
- Value & v2(args[0]->list.elems[i]);
+ Value & v2(*args[0]->list.elems[i]);
state.forceAttrs(v2);
Bindings::iterator j = v2.attrs->find(state.sName);
@@ -815,8 +818,8 @@ static void prim_head(EvalState & state, Value * * args, Value & v)
state.forceList(*args[0]);
if (args[0]->list.length == 0)
throw Error("`head' called on an empty list");
- state.forceValue(args[0]->list.elems[0]);
- v = args[0]->list.elems[0];
+ state.forceValue(*args[0]->list.elems[0]);
+ v = *args[0]->list.elems[0];
}
@@ -840,11 +843,13 @@ static void prim_map(EvalState & state, Value * * args, Value & v)
state.forceList(*args[1]);
state.mkList(v, args[1]->list.length);
+ Value * vs = state.allocValues(v.list.length);
for (unsigned int n = 0; n < v.list.length; ++n) {
- v.list.elems[n].type = tApp;
- v.list.elems[n].app.left = args[0];
- v.list.elems[n].app.right = &args[1]->list.elems[n];
+ v.list.elems[n] = &vs[n];
+ vs[n].type = tApp;
+ vs[n].app.left = args[0];
+ vs[n].app.right = args[1]->list.elems[n];
}
}
diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc
index 0c8fc143c..58e89925c 100644
--- a/src/libexpr/value-to-xml.cc
+++ b/src/libexpr/value-to-xml.cc
@@ -97,7 +97,7 @@ static void printValueAsXML(EvalState & state, bool strict, Value & v,
case tList: {
XMLOpenElement _(doc, "list");
for (unsigned int n = 0; n < v.list.length; ++n)
- printValueAsXML(state, strict, v.list.elems[n], doc, context, drvsSeen);
+ printValueAsXML(state, strict, *v.list.elems[n], doc, context, drvsSeen);
break;
}