diff options
-rw-r--r-- | doc/manual/expressions/builtins.xml | 22 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 33 | ||||
-rw-r--r-- | tests/lang/eval-okay-any-all.exp | 1 | ||||
-rw-r--r-- | tests/lang/eval-okay-any-all.nix | 11 |
4 files changed, 67 insertions, 0 deletions
diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml index 0b11e2f5a5c6..cb987ca02772 100644 --- a/doc/manual/expressions/builtins.xml +++ b/doc/manual/expressions/builtins.xml @@ -39,6 +39,28 @@ available as <function>builtins.derivation</function>.</para> </varlistentry> + <varlistentry><term><function>builtins.all</function> + <replaceable>pred</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the function + <replaceable>pred</replaceable> returns <literal>true</literal> + for all elements of <replaceable>list</replaceable>, + and <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + + <varlistentry><term><function>builtins.any</function> + <replaceable>pred</replaceable> <replaceable>list</replaceable></term> + + <listitem><para>Return <literal>true</literal> if the function + <replaceable>pred</replaceable> returns <literal>true</literal> + for at least one element of <replaceable>list</replaceable>, + and <literal>false</literal> otherwise.</para></listitem> + + </varlistentry> + + <varlistentry><term><function>builtins.attrNames</function> <replaceable>set</replaceable></term> diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index dd21bdc57e4f..d1ad75a286e7 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1333,6 +1333,37 @@ static void prim_foldlStrict(EvalState & state, const Pos & pos, Value * * args, } +static void anyOrAll(bool any, EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + state.forceFunction(*args[0], pos); + state.forceList(*args[1], pos); + + Value vTmp; + for (unsigned int n = 0; n < args[1]->list.length; ++n) { + state.callFunction(*args[0], *args[1]->list.elems[n], vTmp, pos); + bool res = state.forceBool(vTmp); + if (res == any) { + mkBool(v, any); + return; + } + } + + mkBool(v, !any); +} + + +static void prim_any(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + anyOrAll(true, state, pos, args, v); +} + + +static void prim_all(EvalState & state, const Pos & pos, Value * * args, Value & v) +{ + anyOrAll(false, state, pos, args, v); +} + + /************************************************************* * Integer arithmetic *************************************************************/ @@ -1671,6 +1702,8 @@ void EvalState::createBaseEnv() addPrimOp("__concatLists", 1, prim_concatLists); addPrimOp("__length", 1, prim_length); addPrimOp("__foldl'", 3, prim_foldlStrict); + addPrimOp("__any", 2, prim_any); + addPrimOp("__all", 2, prim_all); // Integer arithmetic addPrimOp("__add", 2, prim_add); diff --git a/tests/lang/eval-okay-any-all.exp b/tests/lang/eval-okay-any-all.exp new file mode 100644 index 000000000000..eb273f45b2a6 --- /dev/null +++ b/tests/lang/eval-okay-any-all.exp @@ -0,0 +1 @@ +[ false false true true true true false true ] diff --git a/tests/lang/eval-okay-any-all.nix b/tests/lang/eval-okay-any-all.nix new file mode 100644 index 000000000000..a3f26ea2aa83 --- /dev/null +++ b/tests/lang/eval-okay-any-all.nix @@ -0,0 +1,11 @@ +with builtins; + +[ (any (x: x == 1) []) + (any (x: x == 1) [2 3 4]) + (any (x: x == 1) [1 2 3 4]) + (any (x: x == 1) [4 3 2 1]) + (all (x: x == 1) []) + (all (x: x == 1) [1]) + (all (x: x == 1) [1 2 3]) + (all (x: x == 1) [1 1 1]) +] |