StaticEnv: Use std::vector instead of std::map

This commit is contained in:
Eelco Dolstra 2020-02-21 18:31:16 +01:00
parent c4bd6a15c2
commit ab35cbd675
6 changed files with 55 additions and 22 deletions

View file

@ -583,7 +583,7 @@ Value * EvalState::addConstant(const string & name, Value & v)
{ {
Value * v2 = allocValue(); Value * v2 = allocValue();
*v2 = v; *v2 = v;
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; staticBaseEnv.vars.emplace_back(symbols.create(name), baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v2; baseEnv.values[baseEnvDispl++] = v2;
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2)); baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2));
@ -609,7 +609,7 @@ Value * EvalState::addPrimOp(const string & name,
Value * v = allocValue(); Value * v = allocValue();
v->mkPrimOp(new PrimOp { .fun = primOp, .arity = arity, .name = sym }); v->mkPrimOp(new PrimOp { .fun = primOp, .arity = arity, .name = sym });
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl; staticBaseEnv.vars.emplace_back(symbols.create(name), baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v; baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->attrs->push_back(Attr(sym, v)); baseEnv.values[0]->attrs->push_back(Attr(sym, v));
return v; return v;
@ -635,7 +635,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
Value * v = allocValue(); Value * v = allocValue();
v->mkPrimOp(new PrimOp(std::move(primOp))); v->mkPrimOp(new PrimOp(std::move(primOp)));
staticBaseEnv.vars[envName] = baseEnvDispl; staticBaseEnv.vars.emplace_back(envName, baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v; baseEnv.values[baseEnvDispl++] = v;
baseEnv.values[0]->attrs->push_back(Attr(primOp.name, v)); baseEnv.values[0]->attrs->push_back(Attr(primOp.name, v));
return v; return v;

View file

@ -269,7 +269,7 @@ void ExprVar::bindVars(const StaticEnv & env)
if (curEnv->isWith) { if (curEnv->isWith) {
if (withLevel == -1) withLevel = level; if (withLevel == -1) withLevel = level;
} else { } else {
StaticEnv::Vars::const_iterator i = curEnv->vars.find(name); auto i = curEnv->find(name);
if (i != curEnv->vars.end()) { if (i != curEnv->vars.end()) {
fromWith = false; fromWith = false;
this->level = level; this->level = level;
@ -311,14 +311,16 @@ void ExprOpHasAttr::bindVars(const StaticEnv & env)
void ExprAttrs::bindVars(const StaticEnv & env) void ExprAttrs::bindVars(const StaticEnv & env)
{ {
const StaticEnv * dynamicEnv = &env; const StaticEnv * dynamicEnv = &env;
StaticEnv newEnv(false, &env); StaticEnv newEnv(false, &env, recursive ? attrs.size() : 0);
if (recursive) { if (recursive) {
dynamicEnv = &newEnv; dynamicEnv = &newEnv;
unsigned int displ = 0; unsigned int displ = 0;
for (auto & i : attrs) for (auto & i : attrs)
newEnv.vars[i.first] = i.second.displ = displ++; newEnv.vars.emplace_back(i.first, i.second.displ = displ++);
// No need to sort newEnv since attrs is in sorted order.
for (auto & i : attrs) for (auto & i : attrs)
i.second.e->bindVars(i.second.inherited ? env : newEnv); i.second.e->bindVars(i.second.inherited ? env : newEnv);
@ -342,15 +344,20 @@ void ExprList::bindVars(const StaticEnv & env)
void ExprLambda::bindVars(const StaticEnv & env) void ExprLambda::bindVars(const StaticEnv & env)
{ {
StaticEnv newEnv(false, &env); StaticEnv newEnv(
false, &env,
(hasFormals() ? formals->formals.size() : 0) +
(arg.empty() ? 0 : 1));
unsigned int displ = 0; unsigned int displ = 0;
if (!arg.empty()) newEnv.vars[arg] = displ++; if (!arg.empty()) newEnv.vars.emplace_back(arg, displ++);
if (hasFormals()) { if (hasFormals()) {
for (auto & i : formals->formals) for (auto & i : formals->formals)
newEnv.vars[i.name] = displ++; newEnv.vars.emplace_back(i.name, displ++);
newEnv.sort();
for (auto & i : formals->formals) for (auto & i : formals->formals)
if (i.def) i.def->bindVars(newEnv); if (i.def) i.def->bindVars(newEnv);
@ -361,11 +368,13 @@ void ExprLambda::bindVars(const StaticEnv & env)
void ExprLet::bindVars(const StaticEnv & env) void ExprLet::bindVars(const StaticEnv & env)
{ {
StaticEnv newEnv(false, &env); StaticEnv newEnv(false, &env, attrs->attrs.size());
unsigned int displ = 0; unsigned int displ = 0;
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
newEnv.vars[i.first] = i.second.displ = displ++; newEnv.vars.emplace_back(i.first, i.second.displ = displ++);
// No need to sort newEnv since attrs->attrs is in sorted order.
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
i.second.e->bindVars(i.second.inherited ? env : newEnv); i.second.e->bindVars(i.second.inherited ? env : newEnv);

View file

@ -4,8 +4,6 @@
#include "symbol-table.hh" #include "symbol-table.hh"
#include "error.hh" #include "error.hh"
#include <map>
namespace nix { namespace nix {
@ -342,9 +340,28 @@ struct StaticEnv
{ {
bool isWith; bool isWith;
const StaticEnv * up; const StaticEnv * up;
typedef std::map<Symbol, unsigned int> Vars;
// Note: these must be in sorted order.
typedef std::vector<std::pair<Symbol, unsigned int>> Vars;
Vars vars; Vars vars;
StaticEnv(bool isWith, const StaticEnv * up) : isWith(isWith), up(up) { };
StaticEnv(bool isWith, const StaticEnv * up, size_t expectedSize = 0) : isWith(isWith), up(up) {
vars.reserve(expectedSize);
};
void sort()
{
std::sort(vars.begin(), vars.end(),
[](const Vars::value_type & a, const Vars::value_type & b) { return a.first < b.first; });
}
Vars::const_iterator find(const 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();
}
}; };

View file

@ -126,14 +126,14 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
auto j2 = jAttrs->attrs.find(ad.first); auto j2 = jAttrs->attrs.find(ad.first);
if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error. if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
dupAttr(ad.first, j2->second.pos, ad.second.pos); dupAttr(ad.first, j2->second.pos, ad.second.pos);
jAttrs->attrs[ad.first] = ad.second; jAttrs->attrs.emplace(ad.first, ad.second);
} }
} else { } else {
dupAttr(attrPath, pos, j->second.pos); dupAttr(attrPath, pos, j->second.pos);
} }
} else { } else {
// This attr path is not defined. Let's create it. // This attr path is not defined. Let's create it.
attrs->attrs[i->symbol] = ExprAttrs::AttrDef(e, pos); attrs->attrs.emplace(i->symbol, ExprAttrs::AttrDef(e, pos));
e->setName(i->symbol); e->setName(i->symbol);
} }
} else { } else {
@ -483,7 +483,7 @@ binds
if ($$->attrs.find(i.symbol) != $$->attrs.end()) if ($$->attrs.find(i.symbol) != $$->attrs.end())
dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos); dupAttr(i.symbol, makeCurPos(@3, data), $$->attrs[i.symbol].pos);
Pos pos = makeCurPos(@3, data); Pos pos = makeCurPos(@3, data);
$$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true); $$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true));
} }
} }
| binds INHERIT '(' expr ')' attrs ';' | binds INHERIT '(' expr ')' attrs ';'
@ -492,7 +492,7 @@ binds
for (auto & i : *$6) { for (auto & i : *$6) {
if ($$->attrs.find(i.symbol) != $$->attrs.end()) if ($$->attrs.find(i.symbol) != $$->attrs.end())
dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos); dupAttr(i.symbol, makeCurPos(@6, data), $$->attrs[i.symbol].pos);
$$->attrs[i.symbol] = ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)); $$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), makeCurPos(@6, data)));
} }
} }
| { $$ = new ExprAttrs(makeCurPos(@0, data)); } | { $$ = new ExprAttrs(makeCurPos(@0, data)); }

View file

@ -184,14 +184,17 @@ static void import(EvalState & state, const Pos & pos, Value & vPath, Value * vS
Env * env = &state.allocEnv(vScope->attrs->size()); Env * env = &state.allocEnv(vScope->attrs->size());
env->up = &state.baseEnv; env->up = &state.baseEnv;
StaticEnv staticEnv(false, &state.staticBaseEnv); StaticEnv staticEnv(false, &state.staticBaseEnv, vScope->attrs->size());
unsigned int displ = 0; unsigned int displ = 0;
for (auto & attr : *vScope->attrs) { for (auto & attr : *vScope->attrs) {
staticEnv.vars[attr.name] = displ; staticEnv.vars.emplace_back(attr.name, displ);
env->values[displ++] = attr.value; env->values[displ++] = attr.value;
} }
// No need to call staticEnv.sort(), because
// args[0]->attrs is already sorted.
printTalkative("evaluating file '%1%'", realPath); printTalkative("evaluating file '%1%'", realPath);
Expr * e = state.parseExprFromFile(resolveExprPath(realPath), staticEnv); Expr * e = state.parseExprFromFile(resolveExprPath(realPath), staticEnv);
@ -3726,6 +3729,7 @@ void EvalState::createBaseEnv()
/* Add a wrapper around the derivation primop that computes the /* Add a wrapper around the derivation primop that computes the
`drvPath' and `outPath' attributes lazily. */ `drvPath' and `outPath' attributes lazily. */
staticBaseEnv.sort();
sDerivationNix = symbols.create("//builtin/derivation.nix"); sDerivationNix = symbols.create("//builtin/derivation.nix");
eval(parse( eval(parse(
#include "primops/derivation.nix.gen.hh" #include "primops/derivation.nix.gen.hh"
@ -3735,6 +3739,8 @@ void EvalState::createBaseEnv()
/* Now that we've added all primops, sort the `builtins' set, /* Now that we've added all primops, sort the `builtins' set,
because attribute lookups expect it to be sorted. */ because attribute lookups expect it to be sorted. */
baseEnv.values[0]->attrs->sort(); baseEnv.values[0]->attrs->sort();
staticBaseEnv.sort();
} }

View file

@ -644,7 +644,8 @@ void NixRepl::addVarToScope(const Symbol & name, Value & v)
{ {
if (displ >= envSize) if (displ >= envSize)
throw Error("environment full; cannot add more variables"); throw Error("environment full; cannot add more variables");
staticEnv.vars[name] = displ; staticEnv.vars.emplace_back(name, displ);
staticEnv.sort();
env->values[displ++] = &v; env->values[displ++] = &v;
varNames.insert((string) name); varNames.insert((string) name);
} }