1 : #include "attr-path.hh"
2 : #include "nixexpr-ast.hh"
3 : #include "util.hh"
4 :
5 :
6 : namespace nix {
7 :
8 :
9 16 : bool isAttrs(EvalState & state, Expr e, ATermMap & attrs)
10 : {
11 16 : e = evalExpr(state, e);
12 : ATermList dummy;
13 16 : if (!matchAttrs(e, dummy)) return false;
14 16 : queryAllAttrs(e, attrs, false);
15 16 : return true;
16 : }
17 :
18 :
19 : Expr findAlongAttrPath(EvalState & state, const string & attrPath,
20 111 : const ATermMap & autoArgs, Expr e)
21 : {
22 111 : Strings tokens = tokenizeString(attrPath, ".");
23 :
24 : Error attrError =
25 222 : Error(format("attribute selection path `%1%' does not match expression") % attrPath);
26 :
27 111 : string curPath;
28 :
29 128 : for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) {
30 :
31 17 : if (!curPath.empty()) curPath += ".";
32 17 : curPath += *i;
33 :
34 : /* Is *i an index (integer) or a normal attribute name? */
35 17 : enum { apAttr, apIndex } apType = apAttr;
36 17 : string attr = *i;
37 17 : int attrIndex = -1;
38 17 : if (string2Int(attr, attrIndex)) apType = apIndex;
39 :
40 : /* Evaluate the expression. */
41 17 : e = evalExpr(state, autoCallFunction(evalExpr(state, e), autoArgs));
42 :
43 : /* It should evaluate to either an attribute set or an
44 : expression, according to what is specified in the
45 : attrPath. */
46 :
47 17 : if (apType == apAttr) {
48 :
49 16 : ATermMap attrs;
50 :
51 16 : if (!isAttrs(state, e, attrs))
52 : throw TypeError(
53 : format("the expression selected by the selection path `%1%' should be an attribute set but is %2%")
54 0 : % curPath % showType(e));
55 :
56 16 : e = attrs.get(toATerm(attr));
57 16 : if (!e)
58 0 : throw Error(format("attribute `%1%' in selection path `%2%' not found") % attr % curPath);
59 :
60 : }
61 :
62 1 : else if (apType == apIndex) {
63 :
64 : ATermList es;
65 1 : if (!matchList(e, es))
66 : throw TypeError(
67 : format("the expression selected by the selection path `%1%' should be a list but is %2%")
68 0 : % curPath % showType(e));
69 :
70 1 : e = ATelementAt(es, attrIndex);
71 1 : if (!e)
72 0 : throw Error(format("list index %1% in selection path `%2%' not found") % attrIndex % curPath);
73 :
74 : }
75 :
76 : }
77 :
78 111 : return e;
79 : }
80 :
81 0 :
82 : }
|