forked from lix-project/lix
* Keep attribute sets in sorted order to speed up attribute lookups.
* Simplify the representation of attributes in the AST. * Change the behaviour of listToAttrs() in case of duplicate names.
This commit is contained in:
parent
2dc6d50941
commit
e0b7fb8f27
|
@ -20,14 +20,17 @@ bool parseOptionArg(const string & arg, Strings::iterator & i,
|
||||||
if (i == argsEnd) throw error;
|
if (i == argsEnd) throw error;
|
||||||
string value = *i++;
|
string value = *i++;
|
||||||
|
|
||||||
|
/* !!! check for duplicates! */
|
||||||
Value * v = state.allocValue();
|
Value * v = state.allocValue();
|
||||||
autoArgs[state.symbols.create(name)].value = v;
|
autoArgs.push_back(Attr(state.symbols.create(name), v));
|
||||||
|
|
||||||
if (arg == "--arg")
|
if (arg == "--arg")
|
||||||
state.mkThunk_(*v, parseExprFromString(state, value, absPath(".")));
|
state.mkThunk_(*v, parseExprFromString(state, value, absPath(".")));
|
||||||
else
|
else
|
||||||
mkString(*v, value);
|
mkString(*v, value);
|
||||||
|
|
||||||
|
autoArgs.sort(); // !!! inefficient
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,16 @@ namespace nix {
|
||||||
|
|
||||||
Bindings::iterator Bindings::find(const Symbol & name)
|
Bindings::iterator Bindings::find(const Symbol & name)
|
||||||
{
|
{
|
||||||
iterator i = begin();
|
Attr key(name, 0);
|
||||||
for ( ; i != end() && i->name != name; ++i) ;
|
iterator i = lower_bound(begin(), end(), key);
|
||||||
return i;
|
if (i != end() && i->name == name) return i;
|
||||||
|
return end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Attr & Bindings::operator [] (const Symbol & name)
|
void Bindings::sort()
|
||||||
{
|
{
|
||||||
iterator i = find(name);
|
std::sort(begin(), end());
|
||||||
if (i != end()) return *i;
|
|
||||||
push_back(Attr(name, 0));
|
|
||||||
return back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,12 +176,12 @@ void EvalState::addPrimOp(const string & name,
|
||||||
{
|
{
|
||||||
Value * v = allocValue();
|
Value * v = allocValue();
|
||||||
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
|
||||||
Symbol sym = symbols.create(name);
|
Symbol sym = symbols.create(name2);
|
||||||
v->type = tPrimOp;
|
v->type = tPrimOp;
|
||||||
v->primOp = NEW PrimOp(primOp, arity, sym);
|
v->primOp = NEW PrimOp(primOp, arity, sym);
|
||||||
staticBaseEnv.vars[sym] = baseEnvDispl;
|
staticBaseEnv.vars[symbols.create(name)] = baseEnvDispl;
|
||||||
baseEnv.values[baseEnvDispl++] = v;
|
baseEnv.values[baseEnvDispl++] = v;
|
||||||
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v));
|
baseEnv.values[0]->attrs->push_back(Attr(sym, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -506,31 +504,37 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
|
||||||
|
|
||||||
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v); // !!! reserve size
|
||||||
|
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
/* Create a new environment that contains the attributes in
|
/* Create a new environment that contains the attributes in
|
||||||
this `rec'. */
|
this `rec'. */
|
||||||
Env & env2(state.allocEnv(attrs.size() + inherited.size()));
|
Env & env2(state.allocEnv(attrs.size()));
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
|
|
||||||
unsigned int displ = 0;
|
AttrDefs::iterator overrides = attrs.find(state.sOverrides);
|
||||||
|
bool hasOverrides = overrides != attrs.end();
|
||||||
|
|
||||||
/* The recursive attributes are evaluated in the new
|
/* The recursive attributes are evaluated in the new
|
||||||
environment. */
|
environment, while the inherited attributes are evaluated
|
||||||
foreach (Attrs::iterator, i, attrs) {
|
in the original environment. */
|
||||||
Value * vAttr = state.maybeThunk(env2, i->second.first);
|
unsigned int displ = 0;
|
||||||
env2.values[displ++] = vAttr;
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
v.attrs->push_back(nix::Attr(i->first, vAttr, &i->second.second));
|
if (i->second.inherited) {
|
||||||
}
|
/* !!! handle overrides? */
|
||||||
|
Value * vAttr = state.lookupVar(&env, i->second.var);
|
||||||
/* The inherited attributes, on the other hand, are
|
env2.values[displ++] = vAttr;
|
||||||
evaluated in the original environment. */
|
v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos));
|
||||||
foreach (list<Inherited>::iterator, i, inherited) {
|
} else {
|
||||||
Value * vAttr = state.lookupVar(&env, i->first);
|
Value * vAttr;
|
||||||
env2.values[displ++] = vAttr;
|
if (hasOverrides) {
|
||||||
v.attrs->push_back(nix::Attr(i->first.name, vAttr, &i->second));
|
vAttr = state.allocValue();
|
||||||
}
|
mkThunk(*vAttr, env2, i->second.e);
|
||||||
|
} else
|
||||||
|
vAttr = state.maybeThunk(env2, i->second.e);
|
||||||
|
env2.values[displ++] = vAttr;
|
||||||
|
v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos));
|
||||||
|
}
|
||||||
|
|
||||||
/* If the rec contains an attribute called `__overrides', then
|
/* If the rec contains an attribute called `__overrides', then
|
||||||
evaluate it, and add the attributes in that set to the rec.
|
evaluate it, and add the attributes in that set to the rec.
|
||||||
|
@ -540,30 +544,27 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
still reference the original value, because that value has
|
still reference the original value, because that value has
|
||||||
been substituted into the bodies of the other attributes.
|
been substituted into the bodies of the other attributes.
|
||||||
Hence we need __overrides.) */
|
Hence we need __overrides.) */
|
||||||
Bindings::iterator overrides = v.attrs->find(state.sOverrides);
|
if (hasOverrides) {
|
||||||
if (overrides != v.attrs->end()) {
|
Value * vOverrides = (*v.attrs)[overrides->second.displ].value;
|
||||||
state.forceAttrs(*overrides->value);
|
state.forceAttrs(*vOverrides);
|
||||||
foreach (Bindings::iterator, i, *overrides->value->attrs) {
|
foreach (Bindings::iterator, i, *vOverrides->attrs) {
|
||||||
nix::Attr & a = (*v.attrs)[i->name];
|
AttrDefs::iterator j = attrs.find(i->name);
|
||||||
if (a.value)
|
if (j != attrs.end()) {
|
||||||
env2.values[displs[i->name]] = i->value;
|
(*v.attrs)[j->second.displ] = *i;
|
||||||
a = *i;
|
env2.values[j->second.displ] = i->value;
|
||||||
|
} else
|
||||||
|
v.attrs->push_back(*i);
|
||||||
}
|
}
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
foreach (Attrs::iterator, i, attrs) {
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
nix::Attr & a = (*v.attrs)[i->first];
|
if (i->second.inherited)
|
||||||
a.value = state.maybeThunk(env, i->second.first);
|
v.attrs->push_back(Attr(i->first, state.lookupVar(&env, i->second.var), &i->second.pos));
|
||||||
a.pos = &i->second.second;
|
else
|
||||||
}
|
v.attrs->push_back(Attr(i->first, state.maybeThunk(env, i->second.e), &i->second.pos));
|
||||||
|
|
||||||
foreach (list<Inherited>::iterator, i, inherited) {
|
|
||||||
nix::Attr & a = (*v.attrs)[i->first.name];
|
|
||||||
a.value = state.lookupVar(&env, i->first);
|
|
||||||
a.pos = &i->second;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -572,20 +573,18 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
/* Create a new environment that contains the attributes in this
|
/* Create a new environment that contains the attributes in this
|
||||||
`let'. */
|
`let'. */
|
||||||
Env & env2(state.allocEnv(attrs->attrs.size() + attrs->inherited.size()));
|
Env & env2(state.allocEnv(attrs->attrs.size()));
|
||||||
env2.up = &env;
|
env2.up = &env;
|
||||||
|
|
||||||
unsigned int displ = 0;
|
/* The recursive attributes are evaluated in the new environment,
|
||||||
|
while the inherited attributes are evaluated in the original
|
||||||
/* The recursive attributes are evaluated in the new
|
|
||||||
environment. */
|
environment. */
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
|
unsigned int displ = 0;
|
||||||
env2.values[displ++] = state.maybeThunk(env2, i->second.first);
|
foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
|
||||||
|
if (i->second.inherited)
|
||||||
/* The inherited attributes, on the other hand, are evaluated in
|
env2.values[displ++] = state.lookupVar(&env, i->second.var);
|
||||||
the original environment. */
|
else
|
||||||
foreach (list<ExprAttrs::Inherited>::iterator, i, attrs->inherited)
|
env2.values[displ++] = state.maybeThunk(env2, i->second.e);
|
||||||
env2.values[displ++] = state.lookupVar(&env, i->first);
|
|
||||||
|
|
||||||
state.eval(env2, body, v);
|
state.eval(env2, body, v);
|
||||||
}
|
}
|
||||||
|
@ -764,11 +763,13 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
||||||
foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) {
|
foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) {
|
||||||
Bindings::iterator j = args.find(i->name);
|
Bindings::iterator j = args.find(i->name);
|
||||||
if (j != args.end())
|
if (j != args.end())
|
||||||
(*actualArgs.attrs)[i->name] = *j;
|
actualArgs.attrs->push_back(*j);
|
||||||
else if (!i->def)
|
else if (!i->def)
|
||||||
throwTypeError("cannot auto-call a function that has an argument without a default value (`%1%')", i->name);
|
throwTypeError("cannot auto-call a function that has an argument without a default value (`%1%')", i->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actualArgs.attrs->sort();
|
||||||
|
|
||||||
callFunction(fun, actualArgs, res);
|
callFunction(fun, actualArgs, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,11 +852,27 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (v1.attrs->size() == 0) { v = v2; return; }
|
if (v1.attrs->size() == 0) { v = v2; return; }
|
||||||
if (v2.attrs->size() == 0) { v = v1; return; }
|
if (v2.attrs->size() == 0) { v = v1; return; }
|
||||||
|
|
||||||
state.cloneAttrs(v1, v);
|
state.mkAttrs(v);
|
||||||
|
|
||||||
/* !!! fix */
|
/* Merge the attribute sets, preferring values from the second
|
||||||
foreach (Bindings::iterator, i, *v2.attrs)
|
set. Make sure to keep the resulting vector in sorted
|
||||||
(*v.attrs)[i->name] = *i;
|
order. */
|
||||||
|
Bindings::iterator i = v1.attrs->begin();
|
||||||
|
Bindings::iterator j = v2.attrs->begin();
|
||||||
|
|
||||||
|
while (i != v1.attrs->end() && j != v2.attrs->end()) {
|
||||||
|
if (i->name == j->name) {
|
||||||
|
v.attrs->push_back(*j);
|
||||||
|
++i; ++j;
|
||||||
|
}
|
||||||
|
else if (i->name < j->name)
|
||||||
|
v.attrs->push_back(*i++);
|
||||||
|
else
|
||||||
|
v.attrs->push_back(*j++);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i != v1.attrs->end()) v.attrs->push_back(*i++);
|
||||||
|
while (j != v2.attrs->end()) v.attrs->push_back(*j++);
|
||||||
|
|
||||||
state.nrOpUpdateValuesCopied += v.attrs->size();
|
state.nrOpUpdateValuesCopied += v.attrs->size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ class Bindings : public BindingsBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
iterator find(const Symbol & name);
|
iterator find(const Symbol & name);
|
||||||
Attr & operator [] (const Symbol & name);
|
void sort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,6 +142,10 @@ struct Attr
|
||||||
Attr(Symbol name, Value * value, Pos * pos = &noPos)
|
Attr(Symbol name, Value * value, Pos * pos = &noPos)
|
||||||
: name(name), value(value), pos(pos) { };
|
: name(name), value(value), pos(pos) { };
|
||||||
Attr() : pos(&noPos) { };
|
Attr() : pos(&noPos) { };
|
||||||
|
bool operator < (const Attr & a) const
|
||||||
|
{
|
||||||
|
return name < a.name;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||||
foreach (SortedSymbols::iterator, i, attrs) {
|
foreach (SortedSymbols::iterator, i, attrs) {
|
||||||
startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
|
startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
|
||||||
string pathPrefix2 = addToPath(pathPrefix, i->first);
|
string pathPrefix2 = addToPath(pathPrefix, i->first);
|
||||||
Value & v2(*(*v.attrs)[i->second].value);
|
Value & v2(*v.attrs->find(i->second)->value);
|
||||||
if (combineChannels)
|
if (combineChannels)
|
||||||
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done);
|
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done);
|
||||||
else if (getDerivation(state, v2, pathPrefix2, drvs, done)) {
|
else if (getDerivation(state, v2, pathPrefix2, drvs, done)) {
|
||||||
|
|
|
@ -55,10 +55,11 @@ void ExprAttrs::show(std::ostream & str)
|
||||||
{
|
{
|
||||||
if (recursive) str << "rec ";
|
if (recursive) str << "rec ";
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
foreach (list<Inherited>::iterator, i, inherited)
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
str << "inherit " << i->first.name << "; ";
|
if (i->second.inherited)
|
||||||
foreach (Attrs::iterator, i, attrs)
|
str << "inherit " << i->first << " " << "; ";
|
||||||
str << i->first << " = " << *i->second.first << "; ";
|
else
|
||||||
|
str << i->first << " = " << *i->second.e << "; ";
|
||||||
str << "}";
|
str << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +92,11 @@ void ExprLambda::show(std::ostream & str)
|
||||||
void ExprLet::show(std::ostream & str)
|
void ExprLet::show(std::ostream & str)
|
||||||
{
|
{
|
||||||
str << "let ";
|
str << "let ";
|
||||||
foreach (list<ExprAttrs::Inherited>::iterator, i, attrs->inherited)
|
foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
|
||||||
str << "inherit " << i->first.name << "; ";
|
if (i->second.inherited)
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
|
str << "inherit " << i->first << "; ";
|
||||||
str << i->first << " = " << *i->second.first << "; ";
|
else
|
||||||
|
str << i->first << " = " << *i->second.e << "; ";
|
||||||
str << "in " << *body;
|
str << "in " << *body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,26 +213,18 @@ void ExprAttrs::bindVars(const StaticEnv & env)
|
||||||
StaticEnv newEnv(false, &env);
|
StaticEnv newEnv(false, &env);
|
||||||
|
|
||||||
unsigned int displ = 0;
|
unsigned int displ = 0;
|
||||||
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
|
newEnv.vars[i->first] = i->second.displ = displ++;
|
||||||
|
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs)
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
displs[i->first] = newEnv.vars[i->first] = displ++;
|
if (i->second.inherited) i->second.var.bind(env);
|
||||||
|
else i->second.e->bindVars(newEnv);
|
||||||
foreach (list<Inherited>::iterator, i, inherited) {
|
|
||||||
displs[i->first.name] = newEnv.vars[i->first.name] = displ++;
|
|
||||||
i->first.bind(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs)
|
|
||||||
i->second.first->bindVars(newEnv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs)
|
foreach (AttrDefs::iterator, i, attrs)
|
||||||
i->second.first->bindVars(env);
|
if (i->second.inherited) i->second.var.bind(env);
|
||||||
|
else i->second.e->bindVars(env);
|
||||||
foreach (list<Inherited>::iterator, i, inherited)
|
|
||||||
i->first.bind(env);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExprList::bindVars(const StaticEnv & env)
|
void ExprList::bindVars(const StaticEnv & env)
|
||||||
|
@ -263,17 +257,12 @@ void ExprLet::bindVars(const StaticEnv & env)
|
||||||
StaticEnv newEnv(false, &env);
|
StaticEnv newEnv(false, &env);
|
||||||
|
|
||||||
unsigned int displ = 0;
|
unsigned int displ = 0;
|
||||||
|
foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
|
||||||
|
newEnv.vars[i->first] = i->second.displ = displ++;
|
||||||
|
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
|
foreach (ExprAttrs::AttrDefs::iterator, i, attrs->attrs)
|
||||||
newEnv.vars[i->first] = displ++;
|
if (i->second.inherited) i->second.var.bind(env);
|
||||||
|
else i->second.e->bindVars(newEnv);
|
||||||
foreach (list<ExprAttrs::Inherited>::iterator, i, attrs->inherited) {
|
|
||||||
newEnv.vars[i->first.name] = displ++;
|
|
||||||
i->first.bind(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (ExprAttrs::Attrs::iterator, i, attrs->attrs)
|
|
||||||
i->second.first->bindVars(newEnv);
|
|
||||||
|
|
||||||
body->bindVars(newEnv);
|
body->bindVars(newEnv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ struct VarRef
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
unsigned int displ;
|
unsigned int displ;
|
||||||
|
|
||||||
|
VarRef() { };
|
||||||
VarRef(const Symbol & name) : name(name) { };
|
VarRef(const Symbol & name) : name(name) { };
|
||||||
void bind(const StaticEnv & env);
|
void bind(const StaticEnv & env);
|
||||||
};
|
};
|
||||||
|
@ -131,13 +132,18 @@ struct ExprOpHasAttr : Expr
|
||||||
struct ExprAttrs : Expr
|
struct ExprAttrs : Expr
|
||||||
{
|
{
|
||||||
bool recursive;
|
bool recursive;
|
||||||
typedef std::pair<Expr *, Pos> Attr;
|
struct AttrDef {
|
||||||
typedef std::pair<VarRef, Pos> Inherited;
|
bool inherited;
|
||||||
typedef std::map<Symbol, Attr> Attrs;
|
Expr * e; // if not inherited
|
||||||
Attrs attrs;
|
VarRef var; // if inherited
|
||||||
list<Inherited> inherited;
|
Pos pos;
|
||||||
std::map<Symbol, Pos> attrNames; // used during parsing
|
unsigned int displ; // displacement
|
||||||
std::map<Symbol, unsigned int> displs;
|
AttrDef(Expr * e, const Pos & pos) : inherited(false), e(e), pos(pos) { };
|
||||||
|
AttrDef(const Symbol & name, const Pos & pos) : inherited(true), var(name), pos(pos) { };
|
||||||
|
AttrDef() { };
|
||||||
|
};
|
||||||
|
typedef std::map<Symbol, AttrDef> AttrDefs;
|
||||||
|
AttrDefs attrs;
|
||||||
ExprAttrs() : recursive(false) { };
|
ExprAttrs() : recursive(false) { };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
};
|
};
|
||||||
|
|
|
@ -93,20 +93,20 @@ static void addAttr(ExprAttrs * attrs, const vector<Symbol> & attrPath,
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
foreach (vector<Symbol>::const_iterator, i, attrPath) {
|
foreach (vector<Symbol>::const_iterator, i, attrPath) {
|
||||||
n++;
|
n++;
|
||||||
ExprAttrs::Attrs::iterator j = attrs->attrs.find(*i);
|
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*i);
|
||||||
if (j != attrs->attrs.end()) {
|
if (j != attrs->attrs.end()) {
|
||||||
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.first);
|
if (!j->second.inherited) {
|
||||||
if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos, j->second.second);
|
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
|
||||||
attrs = attrs2;
|
if (!attrs2 || n == attrPath.size()) dupAttr(attrPath, pos, j->second.pos);
|
||||||
|
attrs = attrs2;
|
||||||
|
} else
|
||||||
|
dupAttr(attrPath, pos, j->second.pos);
|
||||||
} else {
|
} else {
|
||||||
if (attrs->attrNames.find(*i) != attrs->attrNames.end())
|
|
||||||
dupAttr(attrPath, pos, attrs->attrNames[*i]);
|
|
||||||
attrs->attrNames[*i] = pos;
|
|
||||||
if (n == attrPath.size())
|
if (n == attrPath.size())
|
||||||
attrs->attrs[*i] = ExprAttrs::Attr(e, pos);
|
attrs->attrs[*i] = ExprAttrs::AttrDef(e, pos);
|
||||||
else {
|
else {
|
||||||
ExprAttrs * nested = new ExprAttrs;
|
ExprAttrs * nested = new ExprAttrs;
|
||||||
attrs->attrs[*i] = ExprAttrs::Attr(nested, pos);
|
attrs->attrs[*i] = ExprAttrs::AttrDef(nested, pos);
|
||||||
attrs = nested;
|
attrs = nested;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,21 +383,19 @@ binds
|
||||||
| binds INHERIT ids ';'
|
| binds INHERIT ids ';'
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
foreach (vector<Symbol>::iterator, i, *$3) {
|
foreach (vector<Symbol>::iterator, i, *$3) {
|
||||||
if ($$->attrNames.find(*i) != $$->attrNames.end())
|
if ($$->attrs.find(*i) != $$->attrs.end())
|
||||||
dupAttr(*i, makeCurPos(@3, data), $$->attrNames[*i]);
|
dupAttr(*i, makeCurPos(@3, data), $$->attrs[*i].pos);
|
||||||
Pos pos = makeCurPos(@3, data);
|
Pos pos = makeCurPos(@3, data);
|
||||||
$$->inherited.push_back(ExprAttrs::Inherited(*i, pos));
|
$$->attrs[*i] = ExprAttrs::AttrDef(*i, pos);
|
||||||
$$->attrNames[*i] = pos;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| binds INHERIT '(' expr ')' ids ';'
|
| binds INHERIT '(' expr ')' ids ';'
|
||||||
{ $$ = $1;
|
{ $$ = $1;
|
||||||
/* !!! Should ensure sharing of the expression in $4. */
|
/* !!! Should ensure sharing of the expression in $4. */
|
||||||
foreach (vector<Symbol>::iterator, i, *$6) {
|
foreach (vector<Symbol>::iterator, i, *$6) {
|
||||||
if ($$->attrNames.find(*i) != $$->attrNames.end())
|
if ($$->attrs.find(*i) != $$->attrs.end())
|
||||||
dupAttr(*i, makeCurPos(@6, data), $$->attrNames[*i]);
|
dupAttr(*i, makeCurPos(@6, data), $$->attrs[*i].pos);
|
||||||
$$->attrs[*i] = ExprAttrs::Attr(new ExprSelect($4, *i), makeCurPos(@6, data));
|
$$->attrs[*i] = ExprAttrs::AttrDef(new ExprSelect($4, *i), makeCurPos(@6, data));
|
||||||
$$->attrNames[*i] = makeCurPos(@6, data);
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
| { $$ = new ExprAttrs; }
|
| { $$ = new ExprAttrs; }
|
||||||
|
|
|
@ -209,14 +209,13 @@ static void prim_tryEval(EvalState & state, Value * * args, Value & v)
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v);
|
||||||
try {
|
try {
|
||||||
state.forceValue(*args[0]);
|
state.forceValue(*args[0]);
|
||||||
printMsg(lvlError, format("%1%") % *args[0]);
|
v.attrs->push_back(Attr(state.symbols.create("value"), args[0]));
|
||||||
(*v.attrs)[state.symbols.create("value")].value = args[0];
|
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("success")), true);
|
mkBool(*state.allocAttr(v, state.symbols.create("success")), true);
|
||||||
printMsg(lvlError, format("%1%") % v);
|
|
||||||
} catch (AssertionError & e) {
|
} catch (AssertionError & e) {
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("value")), false);
|
mkBool(*state.allocAttr(v, state.symbols.create("value")), false);
|
||||||
mkBool(*state.allocAttr(v, state.symbols.create("success")), false);
|
mkBool(*state.allocAttr(v, state.symbols.create("success")), false);
|
||||||
}
|
}
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,6 +487,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v);
|
||||||
mkString(*state.allocAttr(v, state.sOutPath), outPath, singleton<PathSet>(drvPath));
|
mkString(*state.allocAttr(v, state.sOutPath), outPath, singleton<PathSet>(drvPath));
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
|
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -742,7 +742,9 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
|
||||||
names.insert(state.symbols.create(args[1]->list.elems[i]->string.s));
|
names.insert(state.symbols.create(args[1]->list.elems[i]->string.s));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy all attributes not in that set. */
|
/* Copy all attributes not in that set. Note that we don't need
|
||||||
|
to sort v.attrs because it's a subset of an already sorted
|
||||||
|
vector. */
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v);
|
||||||
foreach (Bindings::iterator, i, *args[0]->attrs) {
|
foreach (Bindings::iterator, i, *args[0]->attrs) {
|
||||||
if (names.find(i->name) == names.end())
|
if (names.find(i->name) == names.end())
|
||||||
|
@ -761,6 +763,8 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
|
||||||
|
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v);
|
||||||
|
|
||||||
|
std::set<Symbol> seen;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < args[0]->list.length; ++i) {
|
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);
|
state.forceAttrs(v2);
|
||||||
|
@ -774,10 +778,15 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
|
||||||
if (j2 == v2.attrs->end())
|
if (j2 == v2.attrs->end())
|
||||||
throw TypeError("`value' attribute missing in a call to `listToAttrs'");
|
throw TypeError("`value' attribute missing in a call to `listToAttrs'");
|
||||||
|
|
||||||
Attr & a = (*v.attrs)[state.symbols.create(name)];
|
Symbol sym = state.symbols.create(name);
|
||||||
a.value = j2->value;
|
if (seen.find(sym) == seen.end()) {
|
||||||
a.pos = j2->pos;
|
v.attrs->push_back(Attr(sym, j2->value, j2->pos));
|
||||||
|
seen.insert(sym);
|
||||||
|
}
|
||||||
|
/* !!! Throw an error if `name' already exists? */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -825,6 +834,8 @@ static void prim_functionArgs(EvalState & state, Value * * args, Value & v)
|
||||||
foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals)
|
foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals)
|
||||||
// !!! should optimise booleans (allocate only once)
|
// !!! should optimise booleans (allocate only once)
|
||||||
mkBool(*state.allocAttr(v, i->name), i->def);
|
mkBool(*state.allocAttr(v, i->name), i->def);
|
||||||
|
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1007,6 +1018,7 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v)
|
||||||
state.mkAttrs(v);
|
state.mkAttrs(v);
|
||||||
mkString(*state.allocAttr(v, state.sName), parsed.name);
|
mkString(*state.allocAttr(v, state.sName), parsed.name);
|
||||||
mkString(*state.allocAttr(v, state.symbols.create("version")), parsed.version);
|
mkString(*state.allocAttr(v, state.symbols.create("version")), parsed.version);
|
||||||
|
v.attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1120,6 +1132,10 @@ void EvalState::createBaseEnv()
|
||||||
// Versions
|
// Versions
|
||||||
addPrimOp("__parseDrvName", 1, prim_parseDrvName);
|
addPrimOp("__parseDrvName", 1, prim_parseDrvName);
|
||||||
addPrimOp("__compareVersions", 2, prim_compareVersions);
|
addPrimOp("__compareVersions", 2, prim_compareVersions);
|
||||||
|
|
||||||
|
/* Now that we've added all primops, sort the `builtins' attribute
|
||||||
|
set, because attribute lookups expect it to be sorted. */
|
||||||
|
baseEnv.values[0]->attrs->sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ static void showAttrs(EvalState & state, bool strict, bool location,
|
||||||
names.insert(i->name);
|
names.insert(i->name);
|
||||||
|
|
||||||
foreach (StringSet::iterator, i, names) {
|
foreach (StringSet::iterator, i, names) {
|
||||||
Attr & a(attrs[state.symbols.create(*i)]);
|
Attr & a(*attrs.find(state.symbols.create(*i)));
|
||||||
|
|
||||||
XMLAttrs xmlAttrs;
|
XMLAttrs xmlAttrs;
|
||||||
xmlAttrs["name"] = *i;
|
xmlAttrs["name"] = *i;
|
||||||
|
|
|
@ -132,7 +132,7 @@ static void getAllExprs(EvalState & state,
|
||||||
if (hasSuffix(attrName, ".nix"))
|
if (hasSuffix(attrName, ".nix"))
|
||||||
attrName = string(attrName, 0, attrName.size() - 4);
|
attrName = string(attrName, 0, attrName.size() - 4);
|
||||||
attrs.attrs[state.symbols.create(attrName)] =
|
attrs.attrs[state.symbols.create(attrName)] =
|
||||||
ExprAttrs::Attr(parseExprFromFile(state, absPath(path2)), noPos);
|
ExprAttrs::AttrDef(parseExprFromFile(state, absPath(path2)), noPos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* `path2' is a directory (with no default.nix in it);
|
/* `path2' is a directory (with no default.nix in it);
|
||||||
|
@ -154,7 +154,7 @@ static Expr * loadSourceExpr(EvalState & state, const Path & path)
|
||||||
some system-wide directory). */
|
some system-wide directory). */
|
||||||
ExprAttrs * attrs = new ExprAttrs;
|
ExprAttrs * attrs = new ExprAttrs;
|
||||||
attrs->attrs[state.symbols.create("_combineChannels")] =
|
attrs->attrs[state.symbols.create("_combineChannels")] =
|
||||||
ExprAttrs::Attr(new ExprList(), noPos);
|
ExprAttrs::AttrDef(new ExprList(), noPos);
|
||||||
getAllExprs(state, path, *attrs);
|
getAllExprs(state, path, *attrs);
|
||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,12 +70,13 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
if (drvPath != "")
|
if (drvPath != "")
|
||||||
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state));
|
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state));
|
||||||
|
|
||||||
state.mkAttrs(*state.allocAttr(v, state.sMeta));
|
Value & vMeta = *state.allocAttr(v, state.sMeta);
|
||||||
|
state.mkAttrs(vMeta);
|
||||||
|
|
||||||
MetaInfo meta = i->queryMetaInfo(state);
|
MetaInfo meta = i->queryMetaInfo(state);
|
||||||
|
|
||||||
foreach (MetaInfo::const_iterator, j, meta) {
|
foreach (MetaInfo::const_iterator, j, meta) {
|
||||||
Value & v2(*state.allocAttr(*(*v.attrs)[state.sMeta].value, state.symbols.create(j->first)));
|
Value & v2(*state.allocAttr(vMeta, state.symbols.create(j->first)));
|
||||||
switch (j->second.type) {
|
switch (j->second.type) {
|
||||||
case MetaValue::tpInt: mkInt(v2, j->second.intValue); break;
|
case MetaValue::tpInt: mkInt(v2, j->second.intValue); break;
|
||||||
case MetaValue::tpString: mkString(v2, j->second.stringValue); break;
|
case MetaValue::tpString: mkString(v2, j->second.stringValue); break;
|
||||||
|
@ -92,6 +93,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vMeta.attrs->sort();
|
||||||
|
v.attrs->sort();
|
||||||
|
|
||||||
/* This is only necessary when installing store paths, e.g.,
|
/* This is only necessary when installing store paths, e.g.,
|
||||||
`nix-env -i /nix/store/abcd...-foo'. */
|
`nix-env -i /nix/store/abcd...-foo'. */
|
||||||
store->addTempRoot(i->queryOutPath(state));
|
store->addTempRoot(i->queryOutPath(state));
|
||||||
|
@ -118,7 +122,8 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
||||||
mkString(*state.allocAttr(args, state.sSystem), thisSystem);
|
mkString(*state.allocAttr(args, state.sSystem), thisSystem);
|
||||||
mkString(*state.allocAttr(args, state.symbols.create("manifest")),
|
mkString(*state.allocAttr(args, state.symbols.create("manifest")),
|
||||||
manifestFile, singleton<PathSet>(manifestFile));
|
manifestFile, singleton<PathSet>(manifestFile));
|
||||||
(*args.attrs)[state.symbols.create("derivations")].value = &manifest;
|
args.attrs->push_back(Attr(state.symbols.create("derivations"), &manifest));
|
||||||
|
args.attrs->sort();
|
||||||
mkApp(topLevel, envBuilder, args);
|
mkApp(topLevel, envBuilder, args);
|
||||||
|
|
||||||
/* Evaluate it. */
|
/* Evaluate it. */
|
||||||
|
|
|
@ -7,5 +7,5 @@ let
|
||||||
a = builtins.listToAttrs list;
|
a = builtins.listToAttrs list;
|
||||||
b = builtins.listToAttrs ( list ++ list );
|
b = builtins.listToAttrs ( list ++ list );
|
||||||
r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ];
|
r = builtins.listToAttrs [ (asi "result" [ a b ]) ( asi "throw" (throw "this should not be thrown")) ];
|
||||||
x = builtins.listToAttrs [ (asi "foo" "bla") (asi "foo" "bar") ];
|
x = builtins.listToAttrs [ (asi "foo" "bar") (asi "foo" "bla") ];
|
||||||
in concat (map (x: x.a) r.result) + x.foo
|
in concat (map (x: x.a) r.result) + x.foo
|
||||||
|
|
Loading…
Reference in a new issue