forked from lix-project/lix
* Another experimental feature: a way to truly override attributes in
a rec. This will be very useful to allow end-user customisation of all-packages.nix, for instance globally overriding GCC or some other dependency. The // operator doesn't cut it: you could replace the "gcc" attribute, but all other attributes would continue to reference the original value due to the substitution semantics of rec. The syntax is a bit hacky but this is to allow backwards compatibility.
This commit is contained in:
parent
9279174dde
commit
ca07f3e370
|
@ -170,16 +170,18 @@ static Expr substArgs(EvalState & state,
|
||||||
to attributes substituted with selection expressions on the
|
to attributes substituted with selection expressions on the
|
||||||
original set. E.g., e = `rec {x = f x y; y = x;}' becomes `{x = f
|
original set. E.g., e = `rec {x = f x y; y = x;}' becomes `{x = f
|
||||||
(e.x) (e.y); y = e.x;}'. */
|
(e.x) (e.y); y = e.x;}'. */
|
||||||
LocalNoInline(ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds))
|
LocalNoInline(ATerm expandRec(EvalState & state, ATerm e, ATermList rbnds, ATermList nrbnds))
|
||||||
{
|
{
|
||||||
ATerm name;
|
ATerm name;
|
||||||
Expr e2;
|
Expr e2;
|
||||||
Pos pos;
|
Pos pos;
|
||||||
|
Expr eOverrides = 0;
|
||||||
|
|
||||||
/* Create the substitution list. */
|
/* Create the substitution list. */
|
||||||
ATermMap subs(ATgetLength(rbnds) + ATgetLength(nrbnds));
|
ATermMap subs(ATgetLength(rbnds) + ATgetLength(nrbnds));
|
||||||
for (ATermIterator i(rbnds); i; ++i) {
|
for (ATermIterator i(rbnds); i; ++i) {
|
||||||
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
|
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
|
||||||
|
if (name == sOverrides) eOverrides = e2;
|
||||||
subs.set(name, makeSelect(e, name));
|
subs.set(name, makeSelect(e, name));
|
||||||
}
|
}
|
||||||
for (ATermIterator i(nrbnds); i; ++i) {
|
for (ATermIterator i(nrbnds); i; ++i) {
|
||||||
|
@ -187,6 +189,22 @@ LocalNoInline(ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds))
|
||||||
subs.set(name, e2);
|
subs.set(name, e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the rec contains an attribute called `__overrides', then
|
||||||
|
evaluate it, and add the attributes in that set to the rec.
|
||||||
|
This allows overriding of recursive attributes, which is
|
||||||
|
otherwise not possible. (You can use the // operator to
|
||||||
|
replace an attribute, but other attributes in the rec will
|
||||||
|
still reference the original value, because that value has been
|
||||||
|
substituted into the bodies of the other attributes. Hence we
|
||||||
|
need __overrides.) */
|
||||||
|
ATermMap overrides;
|
||||||
|
if (eOverrides) {
|
||||||
|
eOverrides = evalExpr(state, eOverrides);
|
||||||
|
queryAllAttrs(overrides, overrides, false);
|
||||||
|
foreach (ATermMap::const_iterator, i, overrides)
|
||||||
|
subs.set(i->key, i->value);
|
||||||
|
}
|
||||||
|
|
||||||
Substitution subs_(0, &subs);
|
Substitution subs_(0, &subs);
|
||||||
|
|
||||||
/* Create the non-recursive set. */
|
/* Create the non-recursive set. */
|
||||||
|
@ -196,6 +214,10 @@ LocalNoInline(ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds))
|
||||||
as.set(name, makeAttrRHS(substitute(subs_, e2), pos));
|
as.set(name, makeAttrRHS(substitute(subs_, e2), pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eOverrides)
|
||||||
|
foreach (ATermMap::const_iterator, i, overrides)
|
||||||
|
as.set(i->key, makeAttrRHS(i->value, makeNoPos()));
|
||||||
|
|
||||||
/* Copy the non-recursive bindings. !!! inefficient */
|
/* Copy the non-recursive bindings. !!! inefficient */
|
||||||
for (ATermIterator i(nrbnds); i; ++i) {
|
for (ATermIterator i(nrbnds); i; ++i) {
|
||||||
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
|
if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */
|
||||||
|
@ -667,7 +689,7 @@ Expr evalExpr2(EvalState & state, Expr e)
|
||||||
/* Mutually recursive sets. */
|
/* Mutually recursive sets. */
|
||||||
ATermList rbnds, nrbnds;
|
ATermList rbnds, nrbnds;
|
||||||
if (matchRec(e, rbnds, nrbnds))
|
if (matchRec(e, rbnds, nrbnds))
|
||||||
return expandRec(e, rbnds, nrbnds);
|
return expandRec(state, e, rbnds, nrbnds);
|
||||||
|
|
||||||
/* Conditionals. */
|
/* Conditionals. */
|
||||||
if (matchIf(e, e1, e2, e3))
|
if (matchIf(e, e1, e2, e3))
|
||||||
|
|
|
@ -93,3 +93,4 @@ AttrRHS | Expr Pos | ATerm |
|
||||||
|
|
||||||
eTrue = makeBool(makeTrue())
|
eTrue = makeBool(makeTrue())
|
||||||
eFalse = makeBool(makeFalse())
|
eFalse = makeBool(makeFalse())
|
||||||
|
sOverrides = toATerm("__overrides")
|
||||||
|
|
Loading…
Reference in a new issue