about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2015-07-23T15·03+0200
committerEelco Dolstra <eelco.dolstra@logicblox.com>2015-07-23T15·03+0200
commit61af14a9219bff090b238f15c9def5453087aa5d (patch)
tree1ea17f961d74fb236d0b31c524d19fdfe9678a5c /src/libexpr/primops.cc
parent887bb5fa5a5a7b8b91d371de1a5c8280f9505744 (diff)
Add foldl' primop
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index c36a68ce08..6a4b5b0420 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1304,6 +1304,29 @@ static void prim_length(EvalState & state, const Pos & pos, Value * * args, Valu
 }
 
 
+/* Reduce a list by applying a binary operator, from left to
+   right. The operator is applied strictly. */
+static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args, Value & v)
+{
+    state.forceFunction(*args[0], pos);
+    state.forceList(*args[2], pos);
+
+    Value * vCur = args[1];
+
+    if (args[2]->list.length)
+        for (unsigned int n = 0; n < args[2]->list.length; ++n) {
+            Value vTmp;
+            state.callFunction(*args[0], *vCur, vTmp, pos);
+            vCur = n == args[2]->list.length - 1 ? &v : state.allocValue();
+            state.callFunction(vTmp, *args[2]->list.elems[n], *vCur, pos);
+        }
+    else
+        v = *vCur;
+
+    state.forceValue(v);
+}
+
+
 /*************************************************************
  * Integer arithmetic
  *************************************************************/
@@ -1641,6 +1664,7 @@ void EvalState::createBaseEnv()
     addPrimOp("__elem", 2, prim_elem);
     addPrimOp("__concatLists", 1, prim_concatLists);
     addPrimOp("__length", 1, prim_length);
+    addPrimOp("__foldl'", 3, prim_foldlStrict);
 
     // Integer arithmetic
     addPrimOp("__add", 2, prim_add);