1 : #include "attr-path.hh"
2 : #include "nixexpr-ast.hh"
3 : #include "util.hh"
4 :
5 :
6 : namespace nix {
7 :
8 :
9 : bool isAttrs(EvalState & state, Expr e, ATermMap & attrs)
10 5 : {
11 5 : e = evalExpr(state, e);
12 5 : ATermList dummy;
13 5 : if (!matchAttrs(e, dummy)) return false;
14 5 : queryAllAttrs(e, attrs, false);
15 5 : return true;
16 : }
17 :
18 :
19 : Expr findAlongAttrPath(EvalState & state, const string & attrPath,
20 : const ATermMap & autoArgs, Expr e)
21 61 : {
22 61 : Strings tokens = tokenizeString(attrPath, ".");
23 :
24 : Error attrError =
25 61 : Error(format("attribute selection path `%1%' does not match expression") % attrPath);
26 :
27 61 : string curPath;
28 :
29 67 : for (Strings::iterator i = tokens.begin(); i != tokens.end(); ++i) {
30 :
31 6 : if (!curPath.empty()) curPath += ".";
32 6 : curPath += *i;
33 :
34 : /* Is *i an index (integer) or a normal attribute name? */
35 6 : enum { apAttr, apIndex } apType = apAttr;
36 6 : string attr = *i;
37 6 : int attrIndex = -1;
38 6 : if (string2Int(attr, attrIndex)) apType = apIndex;
39 :
40 : /* Evaluate the expression. */
41 6 : 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 6 : if (apType == apAttr) {
48 :
49 5 : ATermMap attrs(128);
50 :
51 5 : if (!isAttrs(state, e, attrs))
52 0 : 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 5 : e = attrs.get(toATerm(attr));
57 5 : 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 1 : ATermList es;
65 1 : if (!matchList(e, es))
66 0 : throw TypeError(
67 : format("the expression selected by the selection path `%1%' should be a list but is %2%")
68 : % 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 61 : return e;
79 : }
80 :
81 :
82 : }
|