* 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
					
				
					 2 changed files with 25 additions and 2 deletions
				
			
		|  | @ -170,16 +170,18 @@ static Expr substArgs(EvalState & state, | |||
|    to attributes substituted with selection expressions on the | ||||
|    original set.  E.g., e = `rec {x = f x y; y = x;}' becomes `{x = f | ||||
|    (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; | ||||
|     Expr e2; | ||||
|     Pos pos; | ||||
|     Expr eOverrides = 0; | ||||
| 
 | ||||
|     /* Create the substitution list. */ | ||||
|     ATermMap subs(ATgetLength(rbnds) + ATgetLength(nrbnds)); | ||||
|     for (ATermIterator i(rbnds); i; ++i) { | ||||
|         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||
|         if (name == sOverrides) eOverrides = e2; | ||||
|         subs.set(name, makeSelect(e, name)); | ||||
|     } | ||||
|     for (ATermIterator i(nrbnds); i; ++i) { | ||||
|  | @ -187,6 +189,22 @@ LocalNoInline(ATerm expandRec(ATerm e, ATermList rbnds, ATermList nrbnds)) | |||
|         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); | ||||
| 
 | ||||
|     /* 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)); | ||||
|     } | ||||
| 
 | ||||
|     if (eOverrides) | ||||
|         foreach (ATermMap::const_iterator, i, overrides) | ||||
|             as.set(i->key, makeAttrRHS(i->value, makeNoPos())); | ||||
| 
 | ||||
|     /* Copy the non-recursive bindings.  !!! inefficient */ | ||||
|     for (ATermIterator i(nrbnds); i; ++i) { | ||||
|         if (!matchBind(*i, name, e2, pos)) abort(); /* can't happen */ | ||||
|  | @ -667,7 +689,7 @@ Expr evalExpr2(EvalState & state, Expr e) | |||
|     /* Mutually recursive sets. */ | ||||
|     ATermList rbnds, nrbnds; | ||||
|     if (matchRec(e, rbnds, nrbnds)) | ||||
|         return expandRec(e, rbnds, nrbnds); | ||||
|         return expandRec(state, e, rbnds, nrbnds); | ||||
| 
 | ||||
|     /* Conditionals. */ | ||||
|     if (matchIf(e, e1, e2, e3)) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue