Allow using RegisterPrimop to define constants.

This enables plugins to add new constants, as well as new primops.
This commit is contained in:
Shea Levy 2018-02-08 13:00:53 -05:00
parent 88cd2d41ac
commit 081f14a169
No known key found for this signature in database
GPG key ID: 5C0BD6957D86FE27
6 changed files with 15 additions and 6 deletions

View file

@ -750,7 +750,7 @@ builtins.fetchurl {
files will be dlopened by Nix, allowing them to affect files will be dlopened by Nix, allowing them to affect
execution through static initialization. In particular, these execution through static initialization. In particular, these
plugins may construct static instances of RegisterPrimOp to 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, RegisterStoreImplementation to add new store implementations,
and RegisterCommand to add new subcommands to the and RegisterCommand to add new subcommands to the
<literal>nix</literal> command. See the constructors for those <literal>nix</literal> command. See the constructors for those

View file

@ -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(); Value * v2 = allocValue();
*v2 = v; *v2 = v;
@ -412,12 +412,18 @@ void EvalState::addConstant(const string & name, Value & v)
baseEnv.values[baseEnvDispl++] = v2; baseEnv.values[baseEnvDispl++] = v2;
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2)); baseEnv.values[0]->attrs->push_back(Attr(symbols.create(name2), v2));
return v2;
} }
Value * EvalState::addPrimOp(const string & name, Value * EvalState::addPrimOp(const string & name,
unsigned int arity, PrimOpFun primOp) unsigned int arity, PrimOpFun primOp)
{ {
if (arity == 0) {
Value v;
primOp(*this, noPos, nullptr, v);
return addConstant(name, v);
}
Value * v = allocValue(); Value * v = allocValue();
string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name; string name2 = string(name, 0, 2) == "__" ? string(name, 2) : name;
Symbol sym = symbols.create(name2); Symbol sym = symbols.create(name2);

View file

@ -210,7 +210,7 @@ private:
void createBaseEnv(); void createBaseEnv();
void addConstant(const string & name, Value & v); Value * addConstant(const string & name, Value & v);
Value * addPrimOp(const string & name, Value * addPrimOp(const string & name,
unsigned int arity, PrimOpFun primOp); unsigned int arity, PrimOpFun primOp);

View file

@ -9,6 +9,9 @@ struct RegisterPrimOp
{ {
typedef std::vector<std::tuple<std::string, size_t, PrimOpFun>> PrimOps; typedef std::vector<std::tuple<std::string, size_t, PrimOpFun>> PrimOps;
static PrimOps * 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); RegisterPrimOp(std::string name, size_t arity, PrimOpFun fun);
}; };

View file

@ -2,6 +2,6 @@ source common.sh
set -o pipefail 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" ] [ "$res"x = "nullx" ]

View file

@ -2,9 +2,9 @@
using namespace nix; 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); mkNull(v);
} }
static RegisterPrimOp r("constNull", 1, prim_constNull); static RegisterPrimOp r("anotherNull", 0, prim_anotherNull);