about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2019-05-28T20·59+0200
committerEelco Dolstra <edolstra@gmail.com>2019-05-28T20·59+0200
commit9eaebbf575615e05e30bf4f8d7e2cf62967e7703 (patch)
treecdfd072bd1ef3f0dd8ac47cb7ee8534a248ee83c /src/libexpr
parentbfc6bdf222d00d3cb1b0e168a5d55d1a7c9cdb72 (diff)
parentb2f3a7411a509d5df5a189066870a0f02b6523a9 (diff)
Merge branch 'attrPaths' of https://github.com/NinjaTrappeur/nix
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/parser.y26
1 files changed, 23 insertions, 3 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 7870393076b8..97e1a65849e2 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -81,7 +81,9 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
     AttrPath::iterator i;
     // All attrpaths have at least one attr
     assert(!attrPath.empty());
-    for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
+    // Checking attrPath validity.
+    // ===========================
+    for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) { 
         if (i->symbol.set()) {
             ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
             if (j != attrs->attrs.end()) {
@@ -102,11 +104,29 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
             attrs = nested;
         }
     }
-    if (i->symbol.set()) {
+    // Expr insertion.
+    // ==========================
+    if (i->symbol.set()) { 
         ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
         if (j != attrs->attrs.end()) {
-            dupAttr(attrPath, pos, j->second.pos);
+            // This attr path is already defined. However, if both
+            // e and the expr pointed by the attr path are two attribute sets,
+            // we want to merge them.
+            // Otherwise, throw an error.
+            ExprAttrs* ae = dynamic_cast<ExprAttrs *>(e);
+            ExprAttrs* jAttrs = dynamic_cast<ExprAttrs *>(j->second.e);
+            if (jAttrs && ae) {
+                for (auto ad: ae->attrs) {
+                    ExprAttrs::AttrDefs::iterator j2 = jAttrs->attrs.find(ad.first);
+                    if (j2 != jAttrs->attrs.end()) // Attr already defined in iAttrs, error.
+                        dupAttr(ad.first, j2->second.pos, ad.second.pos);
+                    jAttrs->attrs[ad.first] = ad.second;
+                }
+            } else {
+                dupAttr(attrPath, pos, j->second.pos);
+            }
         } else {
+            // This attr path is not defined. Let's create it.
             attrs->attrs[i->symbol] = ExprAttrs::AttrDef(e, pos);
             e->setName(i->symbol);
         }