From 14be783676adbb3517b2f73fee31c6f341575440 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 23 Jul 2015 19:23:11 +0200 Subject: [PATCH] Add primops all and any These are used thousands of times during NixOS evaluation, so it's useful to speed them up. --- doc/manual/expressions/builtins.xml | 22 +++++++++++++++++++ src/libexpr/primops.cc | 33 +++++++++++++++++++++++++++++ tests/lang/eval-okay-any-all.exp | 1 + tests/lang/eval-okay-any-all.nix | 11 ++++++++++ 4 files changed, 67 insertions(+) create mode 100644 tests/lang/eval-okay-any-all.exp create mode 100644 tests/lang/eval-okay-any-all.nix diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml index 0b11e2f5a..cb987ca02 100644 --- a/doc/manual/expressions/builtins.xml +++ b/doc/manual/expressions/builtins.xml @@ -39,6 +39,28 @@ available as builtins.derivation. + builtins.all + pred list + + Return true if the function + pred returns true + for all elements of list, + and false otherwise. + + + + + builtins.any + pred list + + Return true if the function + pred returns true + for at least one element of list, + and false otherwise. + + + + builtins.attrNames set diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index dd21bdc57..d1ad75a28 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 000000000..eb273f45b --- /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 000000000..a3f26ea2a --- /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]) +]