82 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "attr-path.hh"
 | |
| #include "nixexpr-ast.hh"
 | |
| #include "util.hh"
 | |
| 
 | |
| 
 | |
| namespace nix {
 | |
| 
 | |
| 
 | |
| bool isAttrs(EvalState & state, Expr e, ATermMap & attrs)
 | |
| {
 | |
|     e = evalExpr(state, e);
 | |
|     ATermList dummy;
 | |
|     if (!matchAttrs(e, dummy)) return false;
 | |
|     queryAllAttrs(e, attrs, false);
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| 
 | |
| Expr findAlongAttrPath(EvalState & state, const string & attrPath,
 | |
|     const ATermMap & autoArgs, Expr e)
 | |
| {
 | |
|     Strings tokens = tokenizeString(attrPath, ".");
 | |
| 
 | |
|     Error attrError =
 | |
|         Error(format("attribute selection path `%1%' does not match expression") % attrPath);
 | |
| 
 | |
|     string curPath;
 | |
|     
 | |
|     for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) {
 | |
| 
 | |
|         if (!curPath.empty()) curPath += ".";
 | |
|         curPath += *i;
 | |
| 
 | |
|         /* Is *i an index (integer) or a normal attribute name? */
 | |
|         enum { apAttr, apIndex } apType = apAttr;
 | |
|         string attr = *i;
 | |
|         int attrIndex = -1;
 | |
|         if (string2Int(attr, attrIndex)) apType = apIndex;
 | |
| 
 | |
|         /* Evaluate the expression. */
 | |
|         e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs));
 | |
| 
 | |
|         /* It should evaluate to either an attribute set or an
 | |
|            expression, according to what is specified in the
 | |
|            attrPath. */
 | |
| 
 | |
|         if (apType == apAttr) {
 | |
| 
 | |
|             ATermMap attrs;
 | |
| 
 | |
|             if (!isAttrs(state, e, attrs))
 | |
|                 throw TypeError(
 | |
|                     format("the expression selected by the selection path `%1%' should be an attribute set but is %2%")
 | |
|                     % curPath % showType(e));
 | |
|                 
 | |
|             e = attrs.get(toATerm(attr));
 | |
|             if (!e)
 | |
|                 throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath);
 | |
| 
 | |
|         }
 | |
| 
 | |
|         else if (apType == apIndex) {
 | |
| 
 | |
|             ATermList es;
 | |
|             if (!matchList(e, es))
 | |
|                 throw TypeError(
 | |
|                     format("the expression selected by the selection path `%1%' should be a list but is %2%")
 | |
|                     % curPath % showType(e));
 | |
| 
 | |
|             e = ATelementAt(es, attrIndex);
 | |
|             if (!e)
 | |
|                 throw Error(format("list index %1% in selection path `%2%' not found") % attrIndex % curPath);
 | |
|             
 | |
|         }
 | |
|         
 | |
|     }
 | |
|     
 | |
|     return e;
 | |
| }
 | |
| 
 | |
|  
 | |
| }
 |