about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-04T16·15+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2014-10-04T16·15+0200
commitc3f0a489f9d58878c211467a84d7db9dae4e8b5a (patch)
treea5850a431b481a88512a09db78efaa05d8d4c870 /src/libexpr/primops.cc
parentd4fcbe1687c3d212966e43118341622cf69612f3 (diff)
Add primop ‘catAttrs’
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index fb37e21a24bf..a1374a05e12d 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1123,6 +1123,35 @@ static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * ar
 }
 
 
+/* Collect each attribute named `attr' from a list of attribute sets.
+   Sets that don't contain the named attribute are ignored.
+
+   Example:
+     catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
+     => [1 2]
+*/
+static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+    Symbol attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos));
+    state.forceList(*args[1], pos);
+
+    Value * res[args[1]->list.length];
+    unsigned int found = 0;
+
+    for (unsigned int n = 0; n < args[1]->list.length; ++n) {
+        Value & v2(*args[1]->list.elems[n]);
+        state.forceAttrs(v2, pos);
+        Bindings::iterator i = v2.attrs->find(attrName);
+        if (i != v2.attrs->end())
+            res[found++] = i->value;
+    }
+
+    state.mkList(v, found);
+    for (unsigned int n = 0; n < found; ++n)
+        v.list.elems[n] = res[n];
+}
+
+
 /* Return a set containing the names of the formal arguments expected
    by the function `f'.  The value of each attribute is a Boolean
    denoting whether has a default value.  For instance,
@@ -1530,6 +1559,7 @@ void EvalState::createBaseEnv()
     addPrimOp("removeAttrs", 2, prim_removeAttrs);
     addPrimOp("__listToAttrs", 1, prim_listToAttrs);
     addPrimOp("__intersectAttrs", 2, prim_intersectAttrs);
+    addPrimOp("__catAttrs", 2, prim_catAttrs);
     addPrimOp("__functionArgs", 1, prim_functionArgs);
 
     // Lists