about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/command-ref/conf-file.xml2
-rw-r--r--src/libexpr/eval.cc8
-rw-r--r--src/libexpr/eval.hh2
-rw-r--r--src/libexpr/primops.hh3
-rw-r--r--tests/plugins.sh2
-rw-r--r--tests/plugins/plugintest.cc4
6 files changed, 15 insertions, 6 deletions
diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index cede6db3cea7..5c4561f66d86 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -750,7 +750,7 @@ builtins.fetchurl {
         files will be dlopened by Nix, allowing them to affect
         execution through static initialization. In particular, these
         plugins may construct static instances of RegisterPrimOp to
-        add new primops to the expression language,
+        add new primops or constants to the expression language,
         RegisterStoreImplementation to add new store implementations,
         and RegisterCommand to add new subcommands to the
         <literal>nix</literal> command. See the constructors for those
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 0b0a0f7b1790..1f3bbc0a53bd 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -404,7 +404,7 @@ Path EvalState::toRealPath(const Path & path, const PathSet & context)
 };
 
 
-void EvalState::addConstant(const string & name, Value & v)
+Value * EvalState::addConstant(const string & name, Value & v)
 {
     Value * v2 = allocValue();
     *v2 = v;
@@ -412,12 +412,18 @@ void EvalState::addConstant(const string & name, Value & v)
     baseEnv.values[baseEnvDispl++] = v2;
     string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
     baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2));
+    return v2;
 }
 
 
 Value * EvalState::addPrimOp(const string & name,
     unsigned int arity, PrimOpFun primOp)
 {
+    if (arity == 0) {
+        Value v;
+        primOp(*this, noPos, nullptr, v);
+        return addConstant(name, v);
+    }
     Value * v = allocValue();
     string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
     Symbol sym = symbols.create(name2);
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 9e3d30d95f49..51905d7e1c62 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -210,7 +210,7 @@ private:
 
     void createBaseEnv();
 
-    void addConstant(const string & name, Value & v);
+    Value * addConstant(const string & name, Value & v);
 
     Value * addPrimOp(const string & name,
         unsigned int arity, PrimOpFun primOp);
diff --git a/src/libexpr/primops.hh b/src/libexpr/primops.hh
index 39d23b04a5ce..31bf3f84f6c7 100644
--- a/src/libexpr/primops.hh
+++ b/src/libexpr/primops.hh
@@ -9,6 +9,9 @@ struct RegisterPrimOp
 {
     typedef std::vector<std::tuple<std::string, size_t, PrimOpFun>> PrimOps;
     static PrimOps * primOps;
+    /* You can register a constant by passing an arity of 0. fun
+       will get called during EvalState initialization, so there
+       may be primops not yet added and builtins is not yet sorted. */
     RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun);
 };
 
diff --git a/tests/plugins.sh b/tests/plugins.sh
index 6d18d1da0d18..23caf04f3380 100644
--- a/tests/plugins.sh
+++ b/tests/plugins.sh
@@ -2,6 +2,6 @@ source common.sh
 
 set -o pipefail
 
-res=$(nix eval '(builtins.constNull true)' --option plugin-files $PWD/plugins/plugintest.so)
+res=$(nix eval '(builtins.anotherNull)' --option plugin-files $PWD/plugins/plugintest.so)
 
 [ "$res"x = "nullx" ]
diff --git a/tests/plugins/plugintest.cc b/tests/plugins/plugintest.cc
index f788c4814322..6b5e6d7cde21 100644
--- a/tests/plugins/plugintest.cc
+++ b/tests/plugins/plugintest.cc
@@ -2,9 +2,9 @@
 
 using namespace nix;
 
-static void prim_constNull (EvalState & state, const Pos & pos, Value ** args, Value & v)
+static void prim_anotherNull (EvalState & state, const Pos & pos, Value ** args, Value & v)
 {
     mkNull(v);
 }
 
-static RegisterPrimOp r("constNull", 1, prim_constNull);
+static RegisterPrimOp r("anotherNull", 0, prim_anotherNull);