libexpr: Switch StaticEnv to LinearMap
Change-Id: If98bfafce9fa5235fe962274c03c619fe965dd60
This commit is contained in:
+17
-15
@@ -1056,19 +1056,24 @@ template<typename T, typename NameFn, typename ValueFn>
|
||||
void NixRepl::addToScope(T && things, NameFn nameFn, ValueFn valueFn)
|
||||
{
|
||||
size_t added = 0;
|
||||
for (auto && thing : things) {
|
||||
if (displ + 1 >= envSize)
|
||||
throw Error("environment full; cannot add more variables");
|
||||
|
||||
const auto name = nameFn(thing);
|
||||
staticEnv->vars.emplace_back(name, displ);
|
||||
env->values[displ++] = valueFn(thing);
|
||||
varNames.emplace(evaluator.symbols[name]);
|
||||
added++;
|
||||
}
|
||||
staticEnv->vars.unsafe_insert_bulk([&] (auto & map) {
|
||||
auto oldSize = map.size();
|
||||
for (auto && thing : things) {
|
||||
if (displ + 1 >= envSize)
|
||||
throw Error("environment full; cannot add more variables");
|
||||
|
||||
const auto name = nameFn(thing);
|
||||
map.emplace_back(name, displ);
|
||||
env->values[displ++] = valueFn(thing);
|
||||
varNames.emplace(evaluator.symbols[name]);
|
||||
added++;
|
||||
}
|
||||
// safety: we sort the range that we inserted so that we don't have to push that
|
||||
// invariant up to the caller
|
||||
std::sort(map.begin() + oldSize, map.end());
|
||||
});
|
||||
|
||||
staticEnv->sort();
|
||||
staticEnv->deduplicate();
|
||||
if (added > 0) {
|
||||
notice("Added %1% variables.", added);
|
||||
}
|
||||
@@ -1093,14 +1098,11 @@ void NixRepl::addVarToScope(const Symbol name, Value & v)
|
||||
{
|
||||
if (displ >= envSize)
|
||||
throw Error("environment full; cannot add more variables");
|
||||
if (auto oldVar = staticEnv->find(name); oldVar != staticEnv->vars.end()) {
|
||||
staticEnv->vars.erase(oldVar);
|
||||
if (staticEnv->vars.insert_or_assign(name, displ).second) {
|
||||
notice("Updated %s.", evaluator.symbols[name]);
|
||||
} else {
|
||||
notice("Added %s.", evaluator.symbols[name]);
|
||||
}
|
||||
staticEnv->vars.emplace_back(name, displ);
|
||||
staticEnv->sort();
|
||||
env->values[displ++] = &v;
|
||||
varNames.emplace(evaluator.symbols[name]);
|
||||
}
|
||||
|
||||
+2
-2
@@ -549,7 +549,7 @@ void EvalBuiltins::addConstant(const std::string & name, Value * v, Constant inf
|
||||
assert(info.type == gotType);
|
||||
|
||||
/* Install value the base environment. */
|
||||
staticEnv->vars.emplace_back(symbols.create(name), baseEnvDispl);
|
||||
staticEnv->vars.insert_or_assign(symbols.create(name), baseEnvDispl);
|
||||
env.values[baseEnvDispl++] = v;
|
||||
env.values[0]->attrs->push_back(Attr(symbols.create(name2), v));
|
||||
}
|
||||
@@ -584,7 +584,7 @@ Value * EvalBuiltins::addPrimOp(PrimOp && primOp)
|
||||
|
||||
Value * v = mem.allocValue();
|
||||
v->mkPrimOp(new PrimOp(primOp));
|
||||
staticEnv->vars.emplace_back(envName, baseEnvDispl);
|
||||
staticEnv->vars.insert_or_assign(auto(envName), baseEnvDispl);
|
||||
env.values[baseEnvDispl++] = v;
|
||||
env.values[0]->attrs->push_back(Attr(symbols.create(primOp.name), v));
|
||||
return v;
|
||||
|
||||
+14
-9
@@ -465,7 +465,7 @@ void VarBinder::visit(ExprVar & e, std::unique_ptr<Expr> & ptr)
|
||||
if (curEnv->isWith) {
|
||||
if (withLevel == -1) withLevel = level;
|
||||
} else {
|
||||
auto i = curEnv->find(e.name);
|
||||
auto i = curEnv->vars.find(e.name);
|
||||
if (i != curEnv->vars.end()) {
|
||||
if (e.needsRoot && !curEnv->isRoot) {
|
||||
throw ParseError({
|
||||
@@ -523,9 +523,12 @@ std::shared_ptr<const StaticEnv> ExprAttrs::buildRecursiveEnv(const std::shared_
|
||||
{
|
||||
auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs.size());
|
||||
|
||||
Displacement displ = 0;
|
||||
for (auto & i : attrs)
|
||||
newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
|
||||
// safety: the attrs is already sorted
|
||||
newEnv->vars.unsafe_insert_bulk([&] (auto & map) {
|
||||
Displacement displ = 0;
|
||||
for (auto & i : attrs)
|
||||
map.emplace_back(i.first, i.second.displ = displ++);
|
||||
});
|
||||
return newEnv;
|
||||
}
|
||||
|
||||
@@ -662,7 +665,7 @@ void VarBinder::visit(ExprPos & e, std::unique_ptr<Expr> & ptr)
|
||||
std::shared_ptr<const StaticEnv> SimplePattern::buildEnv(const StaticEnv * up)
|
||||
{
|
||||
auto newEnv = std::make_shared<StaticEnv>(nullptr, up, 1);
|
||||
newEnv->vars.emplace_back(name, 0);
|
||||
newEnv->vars.insert_or_assign(name, 0);
|
||||
return newEnv;
|
||||
}
|
||||
|
||||
@@ -677,12 +680,14 @@ std::shared_ptr<const StaticEnv> AttrsPattern::buildEnv(const StaticEnv * up)
|
||||
|
||||
Displacement displ = 0;
|
||||
|
||||
if (name) newEnv->vars.emplace_back(name, displ++);
|
||||
if (name) newEnv->vars.insert_or_assign(name, displ++);
|
||||
|
||||
for (auto & i : formals)
|
||||
newEnv->vars.emplace_back(i.name, displ++);
|
||||
// safety: The formals are already sorted
|
||||
newEnv->vars.unsafe_insert_bulk([&] (auto & map) {
|
||||
for (auto & i : formals)
|
||||
map.emplace_back(i.name, displ++);
|
||||
});
|
||||
|
||||
newEnv->sort();
|
||||
return newEnv;
|
||||
}
|
||||
|
||||
|
||||
+2
-28
@@ -11,6 +11,7 @@
|
||||
#include "lix/libexpr/eval-error.hh"
|
||||
#include "lix/libexpr/pos-idx.hh"
|
||||
#include "lix/libutil/strings.hh"
|
||||
#include "lix/libutil/linear-map.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
@@ -607,9 +608,7 @@ struct StaticEnv
|
||||
ExprWith * isWith;
|
||||
const StaticEnv * up;
|
||||
|
||||
// Note: these must be in sorted order.
|
||||
typedef std::vector<std::pair<Symbol, Displacement>> Vars;
|
||||
Vars vars;
|
||||
LinearMap<Symbol, Displacement> vars;
|
||||
|
||||
/* See ExprVar::needsRoot */
|
||||
bool isRoot = false;
|
||||
@@ -617,31 +616,6 @@ struct StaticEnv
|
||||
StaticEnv(ExprWith * isWith, const StaticEnv * up, size_t expectedSize = 0) : isWith(isWith), up(up) {
|
||||
vars.reserve(expectedSize);
|
||||
};
|
||||
|
||||
void sort()
|
||||
{
|
||||
std::stable_sort(vars.begin(), vars.end(),
|
||||
[](const Vars::value_type & a, const Vars::value_type & b) { return a.first < b.first; });
|
||||
}
|
||||
|
||||
void deduplicate()
|
||||
{
|
||||
auto it = vars.begin(), jt = it, end = vars.end();
|
||||
while (jt != end) {
|
||||
*it = *jt++;
|
||||
while (jt != end && it->first == jt->first) *it = *jt++;
|
||||
it++;
|
||||
}
|
||||
vars.erase(it, end);
|
||||
}
|
||||
|
||||
Vars::const_iterator find(Symbol name) const
|
||||
{
|
||||
Vars::value_type key(name, 0);
|
||||
auto i = std::lower_bound(vars.begin(), vars.end(), key);
|
||||
if (i != vars.end() && i->first == name) return i;
|
||||
return vars.end();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -242,14 +242,14 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v)
|
||||
nullptr, state.ctx.builtins.staticEnv.get(), vScope->attrs->size()
|
||||
);
|
||||
|
||||
unsigned int displ = 0;
|
||||
for (auto & attr : *vScope->attrs) {
|
||||
staticEnv->vars.emplace_back(attr.name, displ);
|
||||
env->values[displ++] = attr.value;
|
||||
}
|
||||
|
||||
// No need to call staticEnv.sort(), because
|
||||
// args[0]->attrs is already sorted.
|
||||
staticEnv->vars.unsafe_insert_bulk([&] (auto & map) {
|
||||
unsigned int displ = 0;
|
||||
for (auto & attr : *vScope->attrs) {
|
||||
// safety: args[0]->attrs is already sorted.
|
||||
map.emplace_back(attr.name, displ);
|
||||
env->values[displ++] = attr.value;
|
||||
}
|
||||
});
|
||||
|
||||
debug("evaluating file '%1%'", path);
|
||||
Expr & e = state.ctx.parseExprFromFile(state.ctx.paths.resolveExprPath(path), staticEnv);
|
||||
@@ -2835,7 +2835,6 @@ void EvalBuiltins::createBaseEnv(const SearchPath & searchPath, const Path & sto
|
||||
because attribute lookups expect it to be sorted. */
|
||||
env.values[0]->attrs->sort();
|
||||
|
||||
staticEnv->sort();
|
||||
staticEnv->isRoot = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user