primops.cc: cleanup
Change-Id: Iae0580e8f44988b8452aef77e67ca2495c342bf6
This commit is contained in:
parent
8035abdc37
commit
09139554a8
1 changed files with 105 additions and 194 deletions
|
@ -1,20 +1,10 @@
|
||||||
#include "archive.hh"
|
|
||||||
#include "derivations.hh"
|
#include "derivations.hh"
|
||||||
#include "downstream-placeholder.hh"
|
|
||||||
#include "eval-inline.hh"
|
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "gc-small-vector.hh"
|
#include "gc-small-vector.hh"
|
||||||
#include "globals.hh"
|
|
||||||
#include "json-to-value.hh"
|
#include "json-to-value.hh"
|
||||||
#include "names.hh"
|
|
||||||
#include "path-references.hh"
|
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "util.hh"
|
|
||||||
#include "value-to-json.hh"
|
|
||||||
#include "value-to-xml.hh"
|
|
||||||
#include "primops.hh"
|
#include "primops.hh"
|
||||||
#include "fetch-to-store.hh"
|
|
||||||
|
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -24,147 +14,20 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
|
||||||
#include <regex>
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Miscellaneous
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* Execute a program and parse its output */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename Callable>
|
|
||||||
static inline void withExceptionContext(Trace trace, Callable&& func)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
catch(Error & e)
|
|
||||||
{
|
|
||||||
e.pushTrace(trace);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Try evaluating the argument. Success => {success=true; value=something;},
|
|
||||||
* else => {success=false; value=false;} */
|
|
||||||
|
|
||||||
/* Return an environment variable. Use with care. */
|
|
||||||
/* Evaluate the first argument, then return the second argument. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Derivations
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
static void derivationStrictInternal(EvalState & state, const std::string & name, Bindings * attrs, Value & v);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Paths
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Creating files
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* Convert the argument (which can be any Nix expression) to an XML
|
|
||||||
representation returned in a string. Not all Nix expressions can
|
|
||||||
be sensibly or completely represented (e.g., functions). */
|
|
||||||
|
|
||||||
|
|
||||||
/* Store a string in the Nix store as a source file that can be used
|
|
||||||
as an input by derivations. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Sets
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/* Determine whether the argument is a set. */
|
|
||||||
|
|
||||||
|
|
||||||
/* Builds a set from a list specifying (name, value) pairs. To be
|
|
||||||
precise, a list [{name = "name1"; value = value1;} ... {name =
|
|
||||||
"nameN"; value = valueN;}] is transformed to {name1 = value1;
|
|
||||||
... nameN = valueN;}. In case of duplicate occurrences of the same
|
|
||||||
name, the first takes precedence. */
|
|
||||||
|
|
||||||
|
|
||||||
/* */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Lists
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Return the first element of a list. */
|
|
||||||
|
|
||||||
|
|
||||||
/* Apply a function to every element of a list. */
|
|
||||||
|
|
||||||
/* Return the length of a list. This is an O(1) time operation. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Integer arithmetic
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* String manipulation
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Versions
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
|
||||||
* Primop registration
|
|
||||||
*************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
RegisterPrimOp::PrimOps * RegisterPrimOp::primOps;
|
RegisterPrimOp::PrimOps * RegisterPrimOp::primOps;
|
||||||
|
|
||||||
|
|
||||||
RegisterPrimOp::RegisterPrimOp(PrimOp && primOp)
|
RegisterPrimOp::RegisterPrimOp(PrimOp && primOp)
|
||||||
{
|
{
|
||||||
if (!primOps) primOps = new PrimOps;
|
if (!primOps) {
|
||||||
|
primOps = new PrimOps;
|
||||||
|
}
|
||||||
primOps->push_back(std::move(primOp));
|
primOps->push_back(std::move(primOp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EvalState::createBaseEnv()
|
void EvalState::createBaseEnv()
|
||||||
{
|
{
|
||||||
baseEnv.up = 0;
|
baseEnv.up = 0;
|
||||||
|
@ -174,9 +37,12 @@ void EvalState::createBaseEnv()
|
||||||
|
|
||||||
/* `builtins' must be first! */
|
/* `builtins' must be first! */
|
||||||
v.mkAttrs(buildBindings(128).finish());
|
v.mkAttrs(buildBindings(128).finish());
|
||||||
addConstant("builtins", v, {
|
addConstant(
|
||||||
.type = nAttrs,
|
"builtins",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nAttrs,
|
||||||
|
.doc = R"(
|
||||||
Contains all the [built-in functions](@docroot@/language/builtins.md) and values.
|
Contains all the [built-in functions](@docroot@/language/builtins.md) and values.
|
||||||
|
|
||||||
Since built-in functions were added over time, [testing for attributes](./operators.md#has-attribute) in `builtins` can be used for graceful fallback on older Nix installations:
|
Since built-in functions were added over time, [testing for attributes](./operators.md#has-attribute) in `builtins` can be used for graceful fallback on older Nix installations:
|
||||||
|
@ -186,12 +52,16 @@ void EvalState::createBaseEnv()
|
||||||
if builtins ? hasContext then builtins.hasContext s else true
|
if builtins ? hasContext then builtins.hasContext s else true
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
v.mkBool(true);
|
v.mkBool(true);
|
||||||
addConstant("true", v, {
|
addConstant(
|
||||||
.type = nBool,
|
"true",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nBool,
|
||||||
|
.doc = R"(
|
||||||
Primitive value.
|
Primitive value.
|
||||||
|
|
||||||
It can be returned by
|
It can be returned by
|
||||||
|
@ -206,12 +76,16 @@ void EvalState::createBaseEnv()
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
v.mkBool(false);
|
v.mkBool(false);
|
||||||
addConstant("false", v, {
|
addConstant(
|
||||||
.type = nBool,
|
"false",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nBool,
|
||||||
|
.doc = R"(
|
||||||
Primitive value.
|
Primitive value.
|
||||||
|
|
||||||
It can be returned by
|
It can be returned by
|
||||||
|
@ -226,12 +100,16 @@ void EvalState::createBaseEnv()
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
v.mkNull();
|
v.mkNull();
|
||||||
addConstant("null", v, {
|
addConstant(
|
||||||
.type = nNull,
|
"null",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nNull,
|
||||||
|
.doc = R"(
|
||||||
Primitive value.
|
Primitive value.
|
||||||
|
|
||||||
The name `null` is not special, and can be shadowed:
|
The name `null` is not special, and can be shadowed:
|
||||||
|
@ -241,14 +119,18 @@ void EvalState::createBaseEnv()
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!evalSettings.pureEval) {
|
if (!evalSettings.pureEval) {
|
||||||
v.mkInt(time(0));
|
v.mkInt(time(0));
|
||||||
}
|
}
|
||||||
addConstant("__currentTime", v, {
|
addConstant(
|
||||||
.type = nInt,
|
"__currentTime",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nInt,
|
||||||
|
.doc = R"(
|
||||||
Return the [Unix time](https://en.wikipedia.org/wiki/Unix_time) at first evaluation.
|
Return the [Unix time](https://en.wikipedia.org/wiki/Unix_time) at first evaluation.
|
||||||
Repeated references to that name will re-use the initially obtained value.
|
Repeated references to that name will re-use the initially obtained value.
|
||||||
|
|
||||||
|
@ -267,14 +149,19 @@ void EvalState::createBaseEnv()
|
||||||
|
|
||||||
The [store path](@docroot@/glossary.md#gloss-store-path) of a derivation depending on `currentTime` will differ for each evaluation, unless both evaluate `builtins.currentTime` in the same second.
|
The [store path](@docroot@/glossary.md#gloss-store-path) of a derivation depending on `currentTime` will differ for each evaluation, unless both evaluate `builtins.currentTime` in the same second.
|
||||||
)",
|
)",
|
||||||
.impureOnly = true,
|
.impureOnly = true,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (!evalSettings.pureEval)
|
if (!evalSettings.pureEval) {
|
||||||
v.mkString(evalSettings.getCurrentSystem());
|
v.mkString(evalSettings.getCurrentSystem());
|
||||||
addConstant("__currentSystem", v, {
|
}
|
||||||
.type = nString,
|
addConstant(
|
||||||
.doc = R"(
|
"__currentSystem",
|
||||||
|
v,
|
||||||
|
{
|
||||||
|
.type = nString,
|
||||||
|
.doc = R"(
|
||||||
The value of the
|
The value of the
|
||||||
[`eval-system`](@docroot@/command-ref/conf-file.md#conf-eval-system)
|
[`eval-system`](@docroot@/command-ref/conf-file.md#conf-eval-system)
|
||||||
or else
|
or else
|
||||||
|
@ -297,13 +184,17 @@ void EvalState::createBaseEnv()
|
||||||
"mips64-linux"
|
"mips64-linux"
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
.impureOnly = true,
|
.impureOnly = true,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
v.mkString("2.18.3-lix");
|
v.mkString("2.18.3-lix");
|
||||||
addConstant("__nixVersion", v, {
|
addConstant(
|
||||||
.type = nString,
|
"__nixVersion",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nString,
|
||||||
|
.doc = R"(
|
||||||
Legacy version of Nix. Always returns "2.18.3-lix" on Lix.
|
Legacy version of Nix. Always returns "2.18.3-lix" on Lix.
|
||||||
|
|
||||||
Code in the Nix language should use other means of feature detection
|
Code in the Nix language should use other means of feature detection
|
||||||
|
@ -314,12 +205,16 @@ void EvalState::createBaseEnv()
|
||||||
If the feature you want to write compatibility code for cannot be
|
If the feature you want to write compatibility code for cannot be
|
||||||
detected by any means, please file a Lix bug.
|
detected by any means, please file a Lix bug.
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
v.mkString(store->storeDir);
|
v.mkString(store->storeDir);
|
||||||
addConstant("__storeDir", v, {
|
addConstant(
|
||||||
.type = nString,
|
"__storeDir",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nString,
|
||||||
|
.doc = R"(
|
||||||
Logical file system location of the [Nix store](@docroot@/glossary.md#gloss-store) currently in use.
|
Logical file system location of the [Nix store](@docroot@/glossary.md#gloss-store) currently in use.
|
||||||
|
|
||||||
This value is determined by the `store` parameter in [Store URLs](@docroot@/command-ref/new-cli/nix3-help-stores.md):
|
This value is determined by the `store` parameter in [Store URLs](@docroot@/command-ref/new-cli/nix3-help-stores.md):
|
||||||
|
@ -329,15 +224,19 @@ void EvalState::createBaseEnv()
|
||||||
"/blah"
|
"/blah"
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/* Legacy language version.
|
/* Legacy language version.
|
||||||
* This is fixed at 6, and will never change in the future on Lix.
|
* This is fixed at 6, and will never change in the future on Lix.
|
||||||
* A better language versioning construct needs to be built instead. */
|
* A better language versioning construct needs to be built instead. */
|
||||||
v.mkInt(6);
|
v.mkInt(6);
|
||||||
addConstant("__langVersion", v, {
|
addConstant(
|
||||||
.type = nInt,
|
"__langVersion",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nInt,
|
||||||
|
.doc = R"(
|
||||||
The legacy version of the Nix language. Always is `6` on Lix,
|
The legacy version of the Nix language. Always is `6` on Lix,
|
||||||
matching Nix 2.18.
|
matching Nix 2.18.
|
||||||
|
|
||||||
|
@ -349,7 +248,8 @@ void EvalState::createBaseEnv()
|
||||||
If the feature you want to write compatibility code for cannot be
|
If the feature you want to write compatibility code for cannot be
|
||||||
detected by any means, please file a Lix bug.
|
detected by any means, please file a Lix bug.
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
if (evalSettings.enableNativeCode) {
|
if (evalSettings.enableNativeCode) {
|
||||||
|
@ -367,7 +267,7 @@ void EvalState::createBaseEnv()
|
||||||
|
|
||||||
addPrimOp({
|
addPrimOp({
|
||||||
.name = "__traceVerbose",
|
.name = "__traceVerbose",
|
||||||
.args = { "e1", "e2" },
|
.args = {"e1", "e2"},
|
||||||
.arity = 2,
|
.arity = 2,
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
Evaluate *e1* and print its abstract syntax representation on standard
|
Evaluate *e1* and print its abstract syntax representation on standard
|
||||||
|
@ -386,9 +286,12 @@ void EvalState::createBaseEnv()
|
||||||
attrs.alloc("prefix").mkString(i.prefix.s);
|
attrs.alloc("prefix").mkString(i.prefix.s);
|
||||||
(v.listElems()[n++] = allocValue())->mkAttrs(attrs);
|
(v.listElems()[n++] = allocValue())->mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
addConstant("__nixPath", v, {
|
addConstant(
|
||||||
.type = nList,
|
"__nixPath",
|
||||||
.doc = R"(
|
v,
|
||||||
|
{
|
||||||
|
.type = nList,
|
||||||
|
.doc = R"(
|
||||||
The search path used to resolve angle bracket path lookups.
|
The search path used to resolve angle bracket path lookups.
|
||||||
|
|
||||||
Angle bracket expressions can be
|
Angle bracket expressions can be
|
||||||
|
@ -406,16 +309,18 @@ void EvalState::createBaseEnv()
|
||||||
builtins.findFile builtins.nixPath "nixpkgs"
|
builtins.findFile builtins.nixPath "nixpkgs"
|
||||||
```
|
```
|
||||||
)",
|
)",
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
if (RegisterPrimOp::primOps)
|
if (RegisterPrimOp::primOps) {
|
||||||
for (auto & primOp : *RegisterPrimOp::primOps)
|
for (auto & primOp : *RegisterPrimOp::primOps) {
|
||||||
if (experimentalFeatureSettings.isEnabled(primOp.experimentalFeature))
|
if (experimentalFeatureSettings.isEnabled(primOp.experimentalFeature)) {
|
||||||
{
|
|
||||||
auto primOpAdjusted = primOp;
|
auto primOpAdjusted = primOp;
|
||||||
primOpAdjusted.arity = std::max(primOp.args.size(), primOp.arity);
|
primOpAdjusted.arity = std::max(primOp.args.size(), primOp.arity);
|
||||||
addPrimOp(std::move(primOpAdjusted));
|
addPrimOp(std::move(primOpAdjusted));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Add a wrapper around the derivation primop that computes the
|
/* Add a wrapper around the derivation primop that computes the
|
||||||
`drvPath' and `outPath' attributes lazily.
|
`drvPath' and `outPath' attributes lazily.
|
||||||
|
@ -423,9 +328,13 @@ void EvalState::createBaseEnv()
|
||||||
Null docs because it is documented separately.
|
Null docs because it is documented separately.
|
||||||
*/
|
*/
|
||||||
auto vDerivation = allocValue();
|
auto vDerivation = allocValue();
|
||||||
addConstant("derivation", vDerivation, {
|
addConstant(
|
||||||
.type = nFunction,
|
"derivation",
|
||||||
});
|
vDerivation,
|
||||||
|
{
|
||||||
|
.type = nFunction,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/* Now that we've added all primops, sort the `builtins' set,
|
/* Now that we've added all primops, sort the `builtins' set,
|
||||||
because attribute lookups expect it to be sorted. */
|
because attribute lookups expect it to be sorted. */
|
||||||
|
@ -436,12 +345,14 @@ void EvalState::createBaseEnv()
|
||||||
/* Note: we have to initialize the 'derivation' constant *after*
|
/* Note: we have to initialize the 'derivation' constant *after*
|
||||||
building baseEnv/staticBaseEnv because it uses 'builtins'. */
|
building baseEnv/staticBaseEnv because it uses 'builtins'. */
|
||||||
char code[] =
|
char code[] =
|
||||||
#include "primops/derivation.nix.gen.hh"
|
#include "primops/derivation.nix.gen.hh"
|
||||||
// the parser needs two NUL bytes as terminators; one of them
|
// the parser needs two NUL bytes as terminators; one of them
|
||||||
// is implied by being a C string.
|
// is implied by being a C string.
|
||||||
"\0";
|
"\0";
|
||||||
eval(parse(code, sizeof(code), derivationInternal, {CanonPath::root}, staticBaseEnv), *vDerivation);
|
eval(
|
||||||
|
parse(code, sizeof(code), derivationInternal, {CanonPath::root}, staticBaseEnv),
|
||||||
|
*vDerivation
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue