mirror of
https://github.com/NixOS/nix
synced 2025-07-07 14:21:48 +02:00
Merge pull request #13407 from xokdvium/smaller-value
libexpr: Reduce the size of Value down to 16 bytes (on 64 bit systems)
This commit is contained in:
commit
c79b8018c0
18 changed files with 976 additions and 308 deletions
|
@ -256,7 +256,6 @@
|
||||||
''^src/libexpr/include/nix/expr/value-to-json\.hh$''
|
''^src/libexpr/include/nix/expr/value-to-json\.hh$''
|
||||||
''^src/libexpr/value-to-xml\.cc$''
|
''^src/libexpr/value-to-xml\.cc$''
|
||||||
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
|
''^src/libexpr/include/nix/expr/value-to-xml\.hh$''
|
||||||
''^src/libexpr/include/nix/expr/value\.hh$''
|
|
||||||
''^src/libexpr/value/context\.cc$''
|
''^src/libexpr/value/context\.cc$''
|
||||||
''^src/libexpr/include/nix/expr/value/context\.hh$''
|
''^src/libexpr/include/nix/expr/value/context\.hh$''
|
||||||
''^src/libfetchers/attrs\.cc$''
|
''^src/libfetchers/attrs\.cc$''
|
||||||
|
|
|
@ -324,7 +324,7 @@ nix_value * nix_get_list_byidx(nix_c_context * context, const nix_value * value,
|
||||||
try {
|
try {
|
||||||
auto & v = check_value_in(value);
|
auto & v = check_value_in(value);
|
||||||
assert(v.type() == nix::nList);
|
assert(v.type() == nix::nList);
|
||||||
auto * p = v.listElems()[ix];
|
auto * p = v.listView()[ix];
|
||||||
nix_gc_incref(nullptr, p);
|
nix_gc_incref(nullptr, p);
|
||||||
if (p != nullptr)
|
if (p != nullptr)
|
||||||
state->state.forceValue(*p, nix::noPos);
|
state->state.forceValue(*p, nix::noPos);
|
||||||
|
|
|
@ -150,8 +150,8 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, attrValues) {
|
TEST_F(PrimOpTest, attrValues) {
|
||||||
auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }");
|
auto v = eval("builtins.attrValues { x = \"foo\"; a = 1; }");
|
||||||
ASSERT_THAT(v, IsListOfSize(2));
|
ASSERT_THAT(v, IsListOfSize(2));
|
||||||
ASSERT_THAT(*v.listElems()[0], IsIntEq(1));
|
ASSERT_THAT(*v.listView()[0], IsIntEq(1));
|
||||||
ASSERT_THAT(*v.listElems()[1], IsStringEq("foo"));
|
ASSERT_THAT(*v.listView()[1], IsStringEq("foo"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, getAttr) {
|
TEST_F(PrimOpTest, getAttr) {
|
||||||
|
@ -250,8 +250,8 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, catAttrs) {
|
TEST_F(PrimOpTest, catAttrs) {
|
||||||
auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]");
|
auto v = eval("builtins.catAttrs \"a\" [{a = 1;} {b = 0;} {a = 2;}]");
|
||||||
ASSERT_THAT(v, IsListOfSize(2));
|
ASSERT_THAT(v, IsListOfSize(2));
|
||||||
ASSERT_THAT(*v.listElems()[0], IsIntEq(1));
|
ASSERT_THAT(*v.listView()[0], IsIntEq(1));
|
||||||
ASSERT_THAT(*v.listElems()[1], IsIntEq(2));
|
ASSERT_THAT(*v.listView()[1], IsIntEq(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, functionArgs) {
|
TEST_F(PrimOpTest, functionArgs) {
|
||||||
|
@ -320,7 +320,8 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, tail) {
|
TEST_F(PrimOpTest, tail) {
|
||||||
auto v = eval("builtins.tail [ 3 2 1 0 ]");
|
auto v = eval("builtins.tail [ 3 2 1 0 ]");
|
||||||
ASSERT_THAT(v, IsListOfSize(3));
|
ASSERT_THAT(v, IsListOfSize(3));
|
||||||
for (const auto [n, elem] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [n, elem] : enumerate(listView))
|
||||||
ASSERT_THAT(*elem, IsIntEq(2 - static_cast<int>(n)));
|
ASSERT_THAT(*elem, IsIntEq(2 - static_cast<int>(n)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,17 +332,17 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, map) {
|
TEST_F(PrimOpTest, map) {
|
||||||
auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]");
|
auto v = eval("map (x: \"foo\" + x) [ \"bar\" \"bla\" \"abc\" ]");
|
||||||
ASSERT_THAT(v, IsListOfSize(3));
|
ASSERT_THAT(v, IsListOfSize(3));
|
||||||
auto elem = v.listElems()[0];
|
auto elem = v.listView()[0];
|
||||||
ASSERT_THAT(*elem, IsThunk());
|
ASSERT_THAT(*elem, IsThunk());
|
||||||
state.forceValue(*elem, noPos);
|
state.forceValue(*elem, noPos);
|
||||||
ASSERT_THAT(*elem, IsStringEq("foobar"));
|
ASSERT_THAT(*elem, IsStringEq("foobar"));
|
||||||
|
|
||||||
elem = v.listElems()[1];
|
elem = v.listView()[1];
|
||||||
ASSERT_THAT(*elem, IsThunk());
|
ASSERT_THAT(*elem, IsThunk());
|
||||||
state.forceValue(*elem, noPos);
|
state.forceValue(*elem, noPos);
|
||||||
ASSERT_THAT(*elem, IsStringEq("foobla"));
|
ASSERT_THAT(*elem, IsStringEq("foobla"));
|
||||||
|
|
||||||
elem = v.listElems()[2];
|
elem = v.listView()[2];
|
||||||
ASSERT_THAT(*elem, IsThunk());
|
ASSERT_THAT(*elem, IsThunk());
|
||||||
state.forceValue(*elem, noPos);
|
state.forceValue(*elem, noPos);
|
||||||
ASSERT_THAT(*elem, IsStringEq("fooabc"));
|
ASSERT_THAT(*elem, IsStringEq("fooabc"));
|
||||||
|
@ -350,7 +351,7 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, filter) {
|
TEST_F(PrimOpTest, filter) {
|
||||||
auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]");
|
auto v = eval("builtins.filter (x: x == 2) [ 3 2 3 2 3 2 ]");
|
||||||
ASSERT_THAT(v, IsListOfSize(3));
|
ASSERT_THAT(v, IsListOfSize(3));
|
||||||
for (const auto elem : v.listItems())
|
for (const auto elem : v.listView())
|
||||||
ASSERT_THAT(*elem, IsIntEq(2));
|
ASSERT_THAT(*elem, IsIntEq(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +368,8 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, concatLists) {
|
TEST_F(PrimOpTest, concatLists) {
|
||||||
auto v = eval("builtins.concatLists [[1 2] [3 4]]");
|
auto v = eval("builtins.concatLists [[1 2] [3 4]]");
|
||||||
ASSERT_THAT(v, IsListOfSize(4));
|
ASSERT_THAT(v, IsListOfSize(4));
|
||||||
for (const auto [i, elem] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [i, elem] : enumerate(listView))
|
||||||
ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1));
|
ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +407,8 @@ namespace nix {
|
||||||
auto v = eval("builtins.genList (x: x + 1) 3");
|
auto v = eval("builtins.genList (x: x + 1) 3");
|
||||||
ASSERT_EQ(v.type(), nList);
|
ASSERT_EQ(v.type(), nList);
|
||||||
ASSERT_EQ(v.listSize(), 3u);
|
ASSERT_EQ(v.listSize(), 3u);
|
||||||
for (const auto [i, elem] : enumerate(v.listItems())) {
|
auto listView = v.listView();
|
||||||
|
for (const auto [i, elem] : enumerate(listView)) {
|
||||||
ASSERT_THAT(*elem, IsThunk());
|
ASSERT_THAT(*elem, IsThunk());
|
||||||
state.forceValue(*elem, noPos);
|
state.forceValue(*elem, noPos);
|
||||||
ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1));
|
ASSERT_THAT(*elem, IsIntEq(static_cast<int>(i)+1));
|
||||||
|
@ -418,7 +421,8 @@ namespace nix {
|
||||||
ASSERT_EQ(v.listSize(), 6u);
|
ASSERT_EQ(v.listSize(), 6u);
|
||||||
|
|
||||||
const std::vector<int> numbers = { 42, 77, 147, 249, 483, 526 };
|
const std::vector<int> numbers = { 42, 77, 147, 249, 483, 526 };
|
||||||
for (const auto [n, elem] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [n, elem] : enumerate(listView))
|
||||||
ASSERT_THAT(*elem, IsIntEq(numbers[n]));
|
ASSERT_THAT(*elem, IsIntEq(numbers[n]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,17 +433,17 @@ namespace nix {
|
||||||
auto right = v.attrs()->get(createSymbol("right"));
|
auto right = v.attrs()->get(createSymbol("right"));
|
||||||
ASSERT_NE(right, nullptr);
|
ASSERT_NE(right, nullptr);
|
||||||
ASSERT_THAT(*right->value, IsListOfSize(2));
|
ASSERT_THAT(*right->value, IsListOfSize(2));
|
||||||
ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23));
|
ASSERT_THAT(*right->value->listView()[0], IsIntEq(23));
|
||||||
ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42));
|
ASSERT_THAT(*right->value->listView()[1], IsIntEq(42));
|
||||||
|
|
||||||
auto wrong = v.attrs()->get(createSymbol("wrong"));
|
auto wrong = v.attrs()->get(createSymbol("wrong"));
|
||||||
ASSERT_NE(wrong, nullptr);
|
ASSERT_NE(wrong, nullptr);
|
||||||
ASSERT_EQ(wrong->value->type(), nList);
|
ASSERT_EQ(wrong->value->type(), nList);
|
||||||
ASSERT_EQ(wrong->value->listSize(), 3u);
|
ASSERT_EQ(wrong->value->listSize(), 3u);
|
||||||
ASSERT_THAT(*wrong->value, IsListOfSize(3));
|
ASSERT_THAT(*wrong->value, IsListOfSize(3));
|
||||||
ASSERT_THAT(*wrong->value->listElems()[0], IsIntEq(1));
|
ASSERT_THAT(*wrong->value->listView()[0], IsIntEq(1));
|
||||||
ASSERT_THAT(*wrong->value->listElems()[1], IsIntEq(9));
|
ASSERT_THAT(*wrong->value->listView()[1], IsIntEq(9));
|
||||||
ASSERT_THAT(*wrong->value->listElems()[2], IsIntEq(3));
|
ASSERT_THAT(*wrong->value->listView()[2], IsIntEq(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, concatMap) {
|
TEST_F(PrimOpTest, concatMap) {
|
||||||
|
@ -448,7 +452,8 @@ namespace nix {
|
||||||
ASSERT_EQ(v.listSize(), 6u);
|
ASSERT_EQ(v.listSize(), 6u);
|
||||||
|
|
||||||
const std::vector<int> numbers = { 1, 2, 0, 3, 4, 0 };
|
const std::vector<int> numbers = { 1, 2, 0, 3, 4, 0 };
|
||||||
for (const auto [n, elem] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [n, elem] : enumerate(listView))
|
||||||
ASSERT_THAT(*elem, IsIntEq(numbers[n]));
|
ASSERT_THAT(*elem, IsIntEq(numbers[n]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +687,8 @@ namespace nix {
|
||||||
ASSERT_THAT(v, IsListOfSize(4));
|
ASSERT_THAT(v, IsListOfSize(4));
|
||||||
|
|
||||||
const std::vector<std::string_view> strings = { "1", "2", "3", "git" };
|
const std::vector<std::string_view> strings = { "1", "2", "3", "git" };
|
||||||
for (const auto [n, p] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [n, p] : enumerate(listView))
|
||||||
ASSERT_THAT(*p, IsStringEq(strings[n]));
|
ASSERT_THAT(*p, IsStringEq(strings[n]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -772,12 +778,12 @@ namespace nix {
|
||||||
auto v = eval("builtins.split \"(a)b\" \"abc\"");
|
auto v = eval("builtins.split \"(a)b\" \"abc\"");
|
||||||
ASSERT_THAT(v, IsListOfSize(3));
|
ASSERT_THAT(v, IsListOfSize(3));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[0], IsStringEq(""));
|
ASSERT_THAT(*v.listView()[0], IsStringEq(""));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[1], IsListOfSize(1));
|
ASSERT_THAT(*v.listView()[1], IsListOfSize(1));
|
||||||
ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a"));
|
ASSERT_THAT(*v.listView()[1]->listView()[0], IsStringEq("a"));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[2], IsStringEq("c"));
|
ASSERT_THAT(*v.listView()[2], IsStringEq("c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, split2) {
|
TEST_F(PrimOpTest, split2) {
|
||||||
|
@ -785,17 +791,17 @@ namespace nix {
|
||||||
auto v = eval("builtins.split \"([ac])\" \"abc\"");
|
auto v = eval("builtins.split \"([ac])\" \"abc\"");
|
||||||
ASSERT_THAT(v, IsListOfSize(5));
|
ASSERT_THAT(v, IsListOfSize(5));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[0], IsStringEq(""));
|
ASSERT_THAT(*v.listView()[0], IsStringEq(""));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[1], IsListOfSize(1));
|
ASSERT_THAT(*v.listView()[1], IsListOfSize(1));
|
||||||
ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a"));
|
ASSERT_THAT(*v.listView()[1]->listView()[0], IsStringEq("a"));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[2], IsStringEq("b"));
|
ASSERT_THAT(*v.listView()[2], IsStringEq("b"));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[3], IsListOfSize(1));
|
ASSERT_THAT(*v.listView()[3], IsListOfSize(1));
|
||||||
ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsStringEq("c"));
|
ASSERT_THAT(*v.listView()[3]->listView()[0], IsStringEq("c"));
|
||||||
|
|
||||||
ASSERT_THAT(*v.listElems()[4], IsStringEq(""));
|
ASSERT_THAT(*v.listView()[4], IsStringEq(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, split3) {
|
TEST_F(PrimOpTest, split3) {
|
||||||
|
@ -803,36 +809,36 @@ namespace nix {
|
||||||
ASSERT_THAT(v, IsListOfSize(5));
|
ASSERT_THAT(v, IsListOfSize(5));
|
||||||
|
|
||||||
// First list element
|
// First list element
|
||||||
ASSERT_THAT(*v.listElems()[0], IsStringEq(""));
|
ASSERT_THAT(*v.listView()[0], IsStringEq(""));
|
||||||
|
|
||||||
// 2nd list element is a list [ "" null ]
|
// 2nd list element is a list [ "" null ]
|
||||||
ASSERT_THAT(*v.listElems()[1], IsListOfSize(2));
|
ASSERT_THAT(*v.listView()[1], IsListOfSize(2));
|
||||||
ASSERT_THAT(*v.listElems()[1]->listElems()[0], IsStringEq("a"));
|
ASSERT_THAT(*v.listView()[1]->listView()[0], IsStringEq("a"));
|
||||||
ASSERT_THAT(*v.listElems()[1]->listElems()[1], IsNull());
|
ASSERT_THAT(*v.listView()[1]->listView()[1], IsNull());
|
||||||
|
|
||||||
// 3rd element
|
// 3rd element
|
||||||
ASSERT_THAT(*v.listElems()[2], IsStringEq("b"));
|
ASSERT_THAT(*v.listView()[2], IsStringEq("b"));
|
||||||
|
|
||||||
// 4th element is a list: [ null "c" ]
|
// 4th element is a list: [ null "c" ]
|
||||||
ASSERT_THAT(*v.listElems()[3], IsListOfSize(2));
|
ASSERT_THAT(*v.listView()[3], IsListOfSize(2));
|
||||||
ASSERT_THAT(*v.listElems()[3]->listElems()[0], IsNull());
|
ASSERT_THAT(*v.listView()[3]->listView()[0], IsNull());
|
||||||
ASSERT_THAT(*v.listElems()[3]->listElems()[1], IsStringEq("c"));
|
ASSERT_THAT(*v.listView()[3]->listView()[1], IsStringEq("c"));
|
||||||
|
|
||||||
// 5th element is the empty string
|
// 5th element is the empty string
|
||||||
ASSERT_THAT(*v.listElems()[4], IsStringEq(""));
|
ASSERT_THAT(*v.listView()[4], IsStringEq(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, split4) {
|
TEST_F(PrimOpTest, split4) {
|
||||||
auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \"");
|
auto v = eval("builtins.split \"([[:upper:]]+)\" \" FOO \"");
|
||||||
ASSERT_THAT(v, IsListOfSize(3));
|
ASSERT_THAT(v, IsListOfSize(3));
|
||||||
auto first = v.listElems()[0];
|
auto first = v.listView()[0];
|
||||||
auto second = v.listElems()[1];
|
auto second = v.listView()[1];
|
||||||
auto third = v.listElems()[2];
|
auto third = v.listView()[2];
|
||||||
|
|
||||||
ASSERT_THAT(*first, IsStringEq(" "));
|
ASSERT_THAT(*first, IsStringEq(" "));
|
||||||
|
|
||||||
ASSERT_THAT(*second, IsListOfSize(1));
|
ASSERT_THAT(*second, IsListOfSize(1));
|
||||||
ASSERT_THAT(*second->listElems()[0], IsStringEq("FOO"));
|
ASSERT_THAT(*second->listView()[0], IsStringEq("FOO"));
|
||||||
|
|
||||||
ASSERT_THAT(*third, IsStringEq(" "));
|
ASSERT_THAT(*third, IsStringEq(" "));
|
||||||
}
|
}
|
||||||
|
@ -850,14 +856,14 @@ namespace nix {
|
||||||
TEST_F(PrimOpTest, match3) {
|
TEST_F(PrimOpTest, match3) {
|
||||||
auto v = eval("builtins.match \"a(b)(c)\" \"abc\"");
|
auto v = eval("builtins.match \"a(b)(c)\" \"abc\"");
|
||||||
ASSERT_THAT(v, IsListOfSize(2));
|
ASSERT_THAT(v, IsListOfSize(2));
|
||||||
ASSERT_THAT(*v.listElems()[0], IsStringEq("b"));
|
ASSERT_THAT(*v.listView()[0], IsStringEq("b"));
|
||||||
ASSERT_THAT(*v.listElems()[1], IsStringEq("c"));
|
ASSERT_THAT(*v.listView()[1], IsStringEq("c"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, match4) {
|
TEST_F(PrimOpTest, match4) {
|
||||||
auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \"");
|
auto v = eval("builtins.match \"[[:space:]]+([[:upper:]]+)[[:space:]]+\" \" FOO \"");
|
||||||
ASSERT_THAT(v, IsListOfSize(1));
|
ASSERT_THAT(v, IsListOfSize(1));
|
||||||
ASSERT_THAT(*v.listElems()[0], IsStringEq("FOO"));
|
ASSERT_THAT(*v.listView()[0], IsStringEq("FOO"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, match5) {
|
TEST_F(PrimOpTest, match5) {
|
||||||
|
@ -874,7 +880,8 @@ namespace nix {
|
||||||
|
|
||||||
// ensure that the list is sorted
|
// ensure that the list is sorted
|
||||||
const std::vector<std::string_view> expected { "a", "x", "y", "z" };
|
const std::vector<std::string_view> expected { "a", "x", "y", "z" };
|
||||||
for (const auto [n, elem] : enumerate(v.listItems()))
|
auto listView = v.listView();
|
||||||
|
for (const auto [n, elem] : enumerate(listView))
|
||||||
ASSERT_THAT(*elem, IsStringEq(expected[n]));
|
ASSERT_THAT(*elem, IsStringEq(expected[n]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||||
if (*attrIndex >= v->listSize())
|
if (*attrIndex >= v->listSize())
|
||||||
throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", *attrIndex, attrPath);
|
throw AttrPathNotFound("list index %1% in selection path '%2%' is out of range", *attrIndex, attrPath);
|
||||||
|
|
||||||
v = v->listElems()[*attrIndex];
|
v = v->listView()[*attrIndex];
|
||||||
pos = noPos;
|
pos = noPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -721,7 +721,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
|
||||||
|
|
||||||
std::vector<std::string> res;
|
std::vector<std::string> res;
|
||||||
|
|
||||||
for (auto & elem : v.listItems())
|
for (auto elem : v.listView())
|
||||||
res.push_back(std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")));
|
res.push_back(std::string(root->state.forceStringNoCtx(*elem, noPos, "while evaluating an attribute for caching")));
|
||||||
|
|
||||||
if (root->db)
|
if (root->db)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "nix/util/config-global.hh"
|
#include "nix/util/config-global.hh"
|
||||||
#include "nix/util/serialise.hh"
|
#include "nix/util/serialise.hh"
|
||||||
#include "nix/expr/eval-gc.hh"
|
#include "nix/expr/eval-gc.hh"
|
||||||
|
#include "nix/expr/value.hh"
|
||||||
|
|
||||||
#include "expr-config-private.hh"
|
#include "expr-config-private.hh"
|
||||||
|
|
||||||
|
@ -52,6 +53,13 @@ static inline void initGCReal()
|
||||||
|
|
||||||
GC_INIT();
|
GC_INIT();
|
||||||
|
|
||||||
|
/* Register valid displacements in case we are using alignment niches
|
||||||
|
for storing the type information. This way tagged pointers are considered
|
||||||
|
to be valid, even when they are not aligned. */
|
||||||
|
if constexpr (detail::useBitPackedValueStorage<sizeof(void *)>)
|
||||||
|
for (std::size_t i = 1; i < sizeof(std::uintptr_t); ++i)
|
||||||
|
GC_register_displacement(i);
|
||||||
|
|
||||||
GC_set_oom_fn(oomHandler);
|
GC_set_oom_fn(oomHandler);
|
||||||
|
|
||||||
/* Set the initial heap size to something fairly big (25% of
|
/* Set the initial heap size to something fairly big (25% of
|
||||||
|
|
|
@ -125,7 +125,7 @@ std::string showType(const Value & v)
|
||||||
// Allow selecting a subset of enum values
|
// Allow selecting a subset of enum values
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||||
switch (v.internalType) {
|
switch (v.getInternalType()) {
|
||||||
case tString: return v.context() ? "a string with context" : "a string";
|
case tString: return v.context() ? "a string with context" : "a string";
|
||||||
case tPrimOp:
|
case tPrimOp:
|
||||||
return fmt("the built-in function '%s'", std::string(v.primOp()->name));
|
return fmt("the built-in function '%s'", std::string(v.primOp()->name));
|
||||||
|
@ -145,7 +145,7 @@ PosIdx Value::determinePos(const PosIdx pos) const
|
||||||
// Allow selecting a subset of enum values
|
// Allow selecting a subset of enum values
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||||
switch (internalType) {
|
switch (getInternalType()) {
|
||||||
case tAttrs: return attrs()->pos;
|
case tAttrs: return attrs()->pos;
|
||||||
case tLambda: return lambda().fun->pos;
|
case tLambda: return lambda().fun->pos;
|
||||||
case tApp: return app().left->determinePos(pos);
|
case tApp: return app().left->determinePos(pos);
|
||||||
|
@ -157,9 +157,8 @@ PosIdx Value::determinePos(const PosIdx pos) const
|
||||||
bool Value::isTrivial() const
|
bool Value::isTrivial() const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
internalType != tApp
|
!isa<tApp, tPrimOpApp>()
|
||||||
&& internalType != tPrimOpApp
|
&& (!isa<tThunk>()
|
||||||
&& (internalType != tThunk
|
|
||||||
|| (dynamic_cast<ExprAttrs *>(thunk().expr)
|
|| (dynamic_cast<ExprAttrs *>(thunk().expr)
|
||||||
&& ((ExprAttrs *) thunk().expr)->dynamicAttrs.empty())
|
&& ((ExprAttrs *) thunk().expr)->dynamicAttrs.empty())
|
||||||
|| dynamic_cast<ExprLambda *>(thunk().expr)
|
|| dynamic_cast<ExprLambda *>(thunk().expr)
|
||||||
|
@ -503,7 +502,7 @@ void EvalState::addConstant(const std::string & name, Value * v, Constant info)
|
||||||
/* Install value the base environment. */
|
/* Install value the base environment. */
|
||||||
staticBaseEnv->vars.emplace_back(symbols.create(name), baseEnvDispl);
|
staticBaseEnv->vars.emplace_back(symbols.create(name), baseEnvDispl);
|
||||||
baseEnv.values[baseEnvDispl++] = v;
|
baseEnv.values[baseEnvDispl++] = v;
|
||||||
getBuiltins().payload.attrs->push_back(Attr(symbols.create(name2), v));
|
const_cast<Bindings *>(getBuiltins().attrs())->push_back(Attr(symbols.create(name2), v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,7 +540,7 @@ const PrimOp * Value::primOpAppPrimOp() const
|
||||||
void Value::mkPrimOp(PrimOp * p)
|
void Value::mkPrimOp(PrimOp * p)
|
||||||
{
|
{
|
||||||
p->check();
|
p->check();
|
||||||
finishValue(tPrimOp, { .primOp = p });
|
setStorage(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -573,7 +572,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
|
||||||
else {
|
else {
|
||||||
staticBaseEnv->vars.emplace_back(envName, baseEnvDispl);
|
staticBaseEnv->vars.emplace_back(envName, baseEnvDispl);
|
||||||
baseEnv.values[baseEnvDispl++] = v;
|
baseEnv.values[baseEnvDispl++] = v;
|
||||||
getBuiltins().payload.attrs->push_back(Attr(symbols.create(primOp.name), v));
|
const_cast<Bindings *>(getBuiltins().attrs())->push_back(Attr(symbols.create(primOp.name), v));
|
||||||
}
|
}
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
@ -2008,9 +2007,10 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * const * lists, co
|
||||||
auto list = buildList(len);
|
auto list = buildList(len);
|
||||||
auto out = list.elems;
|
auto out = list.elems;
|
||||||
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
|
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
|
||||||
auto l = lists[n]->listSize();
|
auto listView = lists[n]->listView();
|
||||||
|
auto l = listView.size();
|
||||||
if (l)
|
if (l)
|
||||||
memcpy(out + pos, lists[n]->listElems(), l * sizeof(Value *));
|
memcpy(out + pos, listView.data(), l * sizeof(Value *));
|
||||||
pos += l;
|
pos += l;
|
||||||
}
|
}
|
||||||
v.mkList(list);
|
v.mkList(list);
|
||||||
|
@ -2175,7 +2175,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (v.isList()) {
|
else if (v.isList()) {
|
||||||
for (auto v2 : v.listItems())
|
for (auto v2 : v.listView())
|
||||||
recurse(*v2);
|
recurse(*v2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2412,7 +2412,8 @@ BackedStringView EvalState::coerceToString(
|
||||||
|
|
||||||
if (v.isList()) {
|
if (v.isList()) {
|
||||||
std::string result;
|
std::string result;
|
||||||
for (auto [n, v2] : enumerate(v.listItems())) {
|
auto listView = v.listView();
|
||||||
|
for (auto [n, v2] : enumerate(listView)) {
|
||||||
try {
|
try {
|
||||||
result += *coerceToString(pos, *v2, context,
|
result += *coerceToString(pos, *v2, context,
|
||||||
"while evaluating one element of the list",
|
"while evaluating one element of the list",
|
||||||
|
@ -2667,7 +2668,7 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
|
||||||
}
|
}
|
||||||
for (size_t n = 0; n < v1.listSize(); ++n) {
|
for (size_t n = 0; n < v1.listSize(); ++n) {
|
||||||
try {
|
try {
|
||||||
assertEqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx);
|
assertEqValues(*v1.listView()[n], *v2.listView()[n], pos, errorCtx);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(positions[pos], "while comparing list element %d", n);
|
e.addTrace(positions[pos], "while comparing list element %d", n);
|
||||||
throw;
|
throw;
|
||||||
|
@ -2819,7 +2820,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
||||||
case nList:
|
case nList:
|
||||||
if (v1.listSize() != v2.listSize()) return false;
|
if (v1.listSize() != v2.listSize()) return false;
|
||||||
for (size_t n = 0; n < v1.listSize(); ++n)
|
for (size_t n = 0; n < v1.listSize(); ++n)
|
||||||
if (!eqValues(*v1.listElems()[n], *v2.listElems()[n], pos, errorCtx)) return false;
|
if (!eqValues(*v1.listView()[n], *v2.listView()[n], pos, errorCtx)) return false;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case nAttrs: {
|
case nAttrs: {
|
||||||
|
|
|
@ -117,7 +117,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
state->forceList(*i->value, i->pos, "while evaluating the 'outputs' attribute of a derivation");
|
state->forceList(*i->value, i->pos, "while evaluating the 'outputs' attribute of a derivation");
|
||||||
|
|
||||||
/* For each output... */
|
/* For each output... */
|
||||||
for (auto elem : i->value->listItems()) {
|
for (auto elem : i->value->listView()) {
|
||||||
std::string output(state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation"));
|
std::string output(state->forceStringNoCtx(*elem, i->pos, "while evaluating the name of an output of a derivation"));
|
||||||
|
|
||||||
if (withPaths) {
|
if (withPaths) {
|
||||||
|
@ -159,7 +159,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
/* ^ this shows during `nix-env -i` right under the bad derivation */
|
/* ^ this shows during `nix-env -i` right under the bad derivation */
|
||||||
if (!outTI->isList()) throw errMsg;
|
if (!outTI->isList()) throw errMsg;
|
||||||
Outputs result;
|
Outputs result;
|
||||||
for (auto elem : outTI->listItems()) {
|
for (auto elem : outTI->listView()) {
|
||||||
if (elem->type() != nString) throw errMsg;
|
if (elem->type() != nString) throw errMsg;
|
||||||
auto out = outputs.find(elem->c_str());
|
auto out = outputs.find(elem->c_str());
|
||||||
if (out == outputs.end()) throw errMsg;
|
if (out == outputs.end()) throw errMsg;
|
||||||
|
@ -206,7 +206,7 @@ bool PackageInfo::checkMeta(Value & v)
|
||||||
{
|
{
|
||||||
state->forceValue(v, v.determinePos(noPos));
|
state->forceValue(v, v.determinePos(noPos));
|
||||||
if (v.type() == nList) {
|
if (v.type() == nList) {
|
||||||
for (auto elem : v.listItems())
|
for (auto elem : v.listView())
|
||||||
if (!checkMeta(*elem)) return false;
|
if (!checkMeta(*elem)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,8 @@ static void getDerivations(EvalState & state, Value & vIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (v.type() == nList) {
|
else if (v.type() == nList) {
|
||||||
for (auto [n, elem] : enumerate(v.listItems())) {
|
auto listView = v.listView();
|
||||||
|
for (auto [n, elem] : enumerate(listView)) {
|
||||||
std::string pathPrefix2 = addToPath(pathPrefix, fmt("%d", n));
|
std::string pathPrefix2 = addToPath(pathPrefix, fmt("%d", n));
|
||||||
if (getDerivation(state, *elem, pathPrefix2, drvs, done, ignoreAssertionFailures))
|
if (getDerivation(state, *elem, pathPrefix2, drvs, done, ignoreAssertionFailures))
|
||||||
getDerivations(state, *elem, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
getDerivations(state, *elem, pathPrefix2, autoArgs, drvs, done, ignoreAssertionFailures);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -415,7 +415,7 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu
|
||||||
void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.exec");
|
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.exec");
|
||||||
auto elems = args[0]->listElems();
|
auto elems = args[0]->listView();
|
||||||
auto count = args[0]->listSize();
|
auto count = args[0]->listSize();
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
state.error<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
|
state.error<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
|
||||||
|
@ -660,8 +660,8 @@ struct CompareValues
|
||||||
return false;
|
return false;
|
||||||
} else if (i == v1->listSize()) {
|
} else if (i == v1->listSize()) {
|
||||||
return true;
|
return true;
|
||||||
} else if (!state.eqValues(*v1->listElems()[i], *v2->listElems()[i], pos, errorCtx)) {
|
} else if (!state.eqValues(*v1->listView()[i], *v2->listView()[i], pos, errorCtx)) {
|
||||||
return (*this)(v1->listElems()[i], v2->listElems()[i], "while comparing two list elements");
|
return (*this)(v1->listView()[i], v2->listView()[i], "while comparing two list elements");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -689,7 +689,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a
|
||||||
state.forceList(*startSet->value, noPos, "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure");
|
state.forceList(*startSet->value, noPos, "while evaluating the 'startSet' attribute passed as argument to builtins.genericClosure");
|
||||||
|
|
||||||
ValueList workSet;
|
ValueList workSet;
|
||||||
for (auto elem : startSet->value->listItems())
|
for (auto elem : startSet->value->listView())
|
||||||
workSet.push_back(elem);
|
workSet.push_back(elem);
|
||||||
|
|
||||||
if (startSet->value->listSize() == 0) {
|
if (startSet->value->listSize() == 0) {
|
||||||
|
@ -727,7 +727,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a
|
||||||
state.forceList(newElements, noPos, "while evaluating the return value of the `operator` passed to builtins.genericClosure");
|
state.forceList(newElements, noPos, "while evaluating the return value of the `operator` passed to builtins.genericClosure");
|
||||||
|
|
||||||
/* Add the values returned by the operator to the work set. */
|
/* Add the values returned by the operator to the work set. */
|
||||||
for (auto elem : newElements.listItems()) {
|
for (auto elem : newElements.listView()) {
|
||||||
state.forceValue(*elem, noPos); // "while evaluating one one of the elements returned by the `operator` passed to builtins.genericClosure");
|
state.forceValue(*elem, noPos); // "while evaluating one one of the elements returned by the `operator` passed to builtins.genericClosure");
|
||||||
workSet.push_back(elem);
|
workSet.push_back(elem);
|
||||||
}
|
}
|
||||||
|
@ -1367,7 +1367,7 @@ static void derivationStrictInternal(
|
||||||
command-line arguments to the builder. */
|
command-line arguments to the builder. */
|
||||||
else if (i->name == state.sArgs) {
|
else if (i->name == state.sArgs) {
|
||||||
state.forceList(*i->value, pos, context_below);
|
state.forceList(*i->value, pos, context_below);
|
||||||
for (auto elem : i->value->listItems()) {
|
for (auto elem : i->value->listView()) {
|
||||||
auto s = state.coerceToString(pos, *elem, context,
|
auto s = state.coerceToString(pos, *elem, context,
|
||||||
"while evaluating an element of the argument list",
|
"while evaluating an element of the argument list",
|
||||||
true).toOwned();
|
true).toOwned();
|
||||||
|
@ -1399,7 +1399,7 @@ static void derivationStrictInternal(
|
||||||
/* Require ‘outputs’ to be a list of strings. */
|
/* Require ‘outputs’ to be a list of strings. */
|
||||||
state.forceList(*i->value, pos, context_below);
|
state.forceList(*i->value, pos, context_below);
|
||||||
Strings ss;
|
Strings ss;
|
||||||
for (auto elem : i->value->listItems())
|
for (auto elem : i->value->listView())
|
||||||
ss.emplace_back(state.forceStringNoCtx(*elem, pos, context_below));
|
ss.emplace_back(state.forceStringNoCtx(*elem, pos, context_below));
|
||||||
handleOutputs(ss);
|
handleOutputs(ss);
|
||||||
}
|
}
|
||||||
|
@ -1882,7 +1882,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
|
|
||||||
LookupPath lookupPath;
|
LookupPath lookupPath;
|
||||||
|
|
||||||
for (auto v2 : args[0]->listItems()) {
|
for (auto v2 : args[0]->listView()) {
|
||||||
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.findFile");
|
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.findFile");
|
||||||
|
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
@ -2920,7 +2920,7 @@ static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value * * args
|
||||||
// 64: large enough to fit the attributes of a derivation
|
// 64: large enough to fit the attributes of a derivation
|
||||||
boost::container::small_vector<Attr, 64> names;
|
boost::container::small_vector<Attr, 64> names;
|
||||||
names.reserve(args[1]->listSize());
|
names.reserve(args[1]->listSize());
|
||||||
for (auto elem : args[1]->listItems()) {
|
for (auto elem : args[1]->listView()) {
|
||||||
state.forceStringNoCtx(*elem, pos, "while evaluating the values of the second argument passed to builtins.removeAttrs");
|
state.forceStringNoCtx(*elem, pos, "while evaluating the values of the second argument passed to builtins.removeAttrs");
|
||||||
names.emplace_back(state.symbols.create(elem->string_view()), nullptr);
|
names.emplace_back(state.symbols.create(elem->string_view()), nullptr);
|
||||||
}
|
}
|
||||||
|
@ -2963,11 +2963,12 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args
|
||||||
state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs");
|
state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs");
|
||||||
|
|
||||||
// Step 1. Sort the name-value attrsets in place using the memory we allocate for the result
|
// Step 1. Sort the name-value attrsets in place using the memory we allocate for the result
|
||||||
size_t listSize = args[0]->listSize();
|
auto listView = args[0]->listView();
|
||||||
|
size_t listSize = listView.size();
|
||||||
auto & bindings = *state.allocBindings(listSize);
|
auto & bindings = *state.allocBindings(listSize);
|
||||||
using ElemPtr = decltype(&bindings[0].value);
|
using ElemPtr = decltype(&bindings[0].value);
|
||||||
|
|
||||||
for (const auto & [n, v2] : enumerate(args[0]->listItems())) {
|
for (const auto & [n, v2] : enumerate(listView)) {
|
||||||
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.listToAttrs");
|
state.forceAttrs(*v2, pos, "while evaluating an element of the list passed to builtins.listToAttrs");
|
||||||
|
|
||||||
auto j = state.getAttr(state.sName, v2->attrs(), "in a {name=...; value=...;} pair");
|
auto j = state.getAttr(state.sName, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||||
|
@ -3122,7 +3123,7 @@ static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, V
|
||||||
SmallValueVector<nonRecursiveStackReservation> res(args[1]->listSize());
|
SmallValueVector<nonRecursiveStackReservation> res(args[1]->listSize());
|
||||||
size_t found = 0;
|
size_t found = 0;
|
||||||
|
|
||||||
for (auto v2 : args[1]->listItems()) {
|
for (auto v2 : args[1]->listView()) {
|
||||||
state.forceAttrs(*v2, pos, "while evaluating an element in the list passed as second argument to builtins.catAttrs");
|
state.forceAttrs(*v2, pos, "while evaluating an element in the list passed as second argument to builtins.catAttrs");
|
||||||
if (auto i = v2->attrs()->get(attrName))
|
if (auto i = v2->attrs()->get(attrName))
|
||||||
res[found++] = i->value;
|
res[found++] = i->value;
|
||||||
|
@ -3247,7 +3248,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
|
||||||
|
|
||||||
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith");
|
state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.zipAttrsWith");
|
||||||
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith");
|
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.zipAttrsWith");
|
||||||
const auto listItems = args[1]->listItems();
|
const auto listItems = args[1]->listView();
|
||||||
|
|
||||||
for (auto & vElem : listItems) {
|
for (auto & vElem : listItems) {
|
||||||
state.forceAttrs(*vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith");
|
state.forceAttrs(*vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith");
|
||||||
|
@ -3346,8 +3347,8 @@ static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Val
|
||||||
n,
|
n,
|
||||||
args[0]->listSize()
|
args[0]->listSize()
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
state.forceValue(*args[0]->listElems()[n], pos);
|
state.forceValue(*args[0]->listView()[n], pos);
|
||||||
v = *args[0]->listElems()[n];
|
v = *args[0]->listView()[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_elemAt({
|
static RegisterPrimOp primop_elemAt({
|
||||||
|
@ -3368,8 +3369,8 @@ static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
state.error<EvalError>(
|
state.error<EvalError>(
|
||||||
"'builtins.head' called on an empty list"
|
"'builtins.head' called on an empty list"
|
||||||
).atPos(pos).debugThrow();
|
).atPos(pos).debugThrow();
|
||||||
state.forceValue(*args[0]->listElems()[0], pos);
|
state.forceValue(*args[0]->listView()[0], pos);
|
||||||
v = *args[0]->listElems()[0];
|
v = *args[0]->listView()[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_head({
|
static RegisterPrimOp primop_head({
|
||||||
|
@ -3394,7 +3395,7 @@ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
|
|
||||||
auto list = state.buildList(args[0]->listSize() - 1);
|
auto list = state.buildList(args[0]->listSize() - 1);
|
||||||
for (const auto & [n, v] : enumerate(list))
|
for (const auto & [n, v] : enumerate(list))
|
||||||
v = args[0]->listElems()[n + 1];
|
v = args[0]->listView()[n + 1];
|
||||||
v.mkList(list);
|
v.mkList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3429,7 +3430,7 @@ static void prim_map(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
auto list = state.buildList(args[1]->listSize());
|
auto list = state.buildList(args[1]->listSize());
|
||||||
for (const auto & [n, v] : enumerate(list))
|
for (const auto & [n, v] : enumerate(list))
|
||||||
(v = state.allocValue())->mkApp(
|
(v = state.allocValue())->mkApp(
|
||||||
args[0], args[1]->listElems()[n]);
|
args[0], args[1]->listView()[n]);
|
||||||
v.mkList(list);
|
v.mkList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3470,9 +3471,9 @@ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Val
|
||||||
bool same = true;
|
bool same = true;
|
||||||
for (size_t n = 0; n < len; ++n) {
|
for (size_t n = 0; n < len; ++n) {
|
||||||
Value res;
|
Value res;
|
||||||
state.callFunction(*args[0], *args[1]->listElems()[n], res, noPos);
|
state.callFunction(*args[0], *args[1]->listView()[n], res, noPos);
|
||||||
if (state.forceBool(res, pos, "while evaluating the return value of the filtering function passed to builtins.filter"))
|
if (state.forceBool(res, pos, "while evaluating the return value of the filtering function passed to builtins.filter"))
|
||||||
vs[k++] = args[1]->listElems()[n];
|
vs[k++] = args[1]->listView()[n];
|
||||||
else
|
else
|
||||||
same = false;
|
same = false;
|
||||||
}
|
}
|
||||||
|
@ -3501,7 +3502,7 @@ static void prim_elem(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.elem");
|
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.elem");
|
||||||
for (auto elem : args[1]->listItems())
|
for (auto elem : args[1]->listView())
|
||||||
if (state.eqValues(*args[0], *elem, pos, "while searching for the presence of the given element in the list")) {
|
if (state.eqValues(*args[0], *elem, pos, "while searching for the presence of the given element in the list")) {
|
||||||
res = true;
|
res = true;
|
||||||
break;
|
break;
|
||||||
|
@ -3523,7 +3524,8 @@ static RegisterPrimOp primop_elem({
|
||||||
static void prim_concatLists(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
static void prim_concatLists(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||||
{
|
{
|
||||||
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.concatLists");
|
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.concatLists");
|
||||||
state.concatLists(v, args[0]->listSize(), args[0]->listElems(), pos, "while evaluating a value of the list passed to builtins.concatLists");
|
auto listView = args[0]->listView();
|
||||||
|
state.concatLists(v, args[0]->listSize(), listView.data(), pos, "while evaluating a value of the list passed to builtins.concatLists");
|
||||||
}
|
}
|
||||||
|
|
||||||
static RegisterPrimOp primop_concatLists({
|
static RegisterPrimOp primop_concatLists({
|
||||||
|
@ -3561,7 +3563,8 @@ static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args
|
||||||
if (args[2]->listSize()) {
|
if (args[2]->listSize()) {
|
||||||
Value * vCur = args[1];
|
Value * vCur = args[1];
|
||||||
|
|
||||||
for (auto [n, elem] : enumerate(args[2]->listItems())) {
|
auto listView = args[2]->listView();
|
||||||
|
for (auto [n, elem] : enumerate(listView)) {
|
||||||
Value * vs []{vCur, elem};
|
Value * vs []{vCur, elem};
|
||||||
vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue();
|
vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue();
|
||||||
state.callFunction(*args[0], vs, *vCur, pos);
|
state.callFunction(*args[0], vs, *vCur, pos);
|
||||||
|
@ -3603,7 +3606,7 @@ static void anyOrAll(bool any, EvalState & state, const PosIdx pos, Value * * ar
|
||||||
: "while evaluating the return value of the function passed to builtins.all";
|
: "while evaluating the return value of the function passed to builtins.all";
|
||||||
|
|
||||||
Value vTmp;
|
Value vTmp;
|
||||||
for (auto elem : args[1]->listItems()) {
|
for (auto elem : args[1]->listView()) {
|
||||||
state.callFunction(*args[0], *elem, vTmp, pos);
|
state.callFunction(*args[0], *elem, vTmp, pos);
|
||||||
bool res = state.forceBool(vTmp, pos, errorCtx);
|
bool res = state.forceBool(vTmp, pos, errorCtx);
|
||||||
if (res == any) {
|
if (res == any) {
|
||||||
|
@ -3701,7 +3704,7 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value
|
||||||
|
|
||||||
auto list = state.buildList(len);
|
auto list = state.buildList(len);
|
||||||
for (const auto & [n, v] : enumerate(list))
|
for (const auto & [n, v] : enumerate(list))
|
||||||
state.forceValue(*(v = args[1]->listElems()[n]), pos);
|
state.forceValue(*(v = args[1]->listView()[n]), pos);
|
||||||
|
|
||||||
auto comparator = [&](Value * a, Value * b) {
|
auto comparator = [&](Value * a, Value * b) {
|
||||||
/* Optimization: if the comparator is lessThan, bypass
|
/* Optimization: if the comparator is lessThan, bypass
|
||||||
|
@ -3787,7 +3790,7 @@ static void prim_partition(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
ValueVector right, wrong;
|
ValueVector right, wrong;
|
||||||
|
|
||||||
for (size_t n = 0; n < len; ++n) {
|
for (size_t n = 0; n < len; ++n) {
|
||||||
auto vElem = args[1]->listElems()[n];
|
auto vElem = args[1]->listView()[n];
|
||||||
state.forceValue(*vElem, pos);
|
state.forceValue(*vElem, pos);
|
||||||
Value res;
|
Value res;
|
||||||
state.callFunction(*args[0], *vElem, res, pos);
|
state.callFunction(*args[0], *vElem, res, pos);
|
||||||
|
@ -3844,7 +3847,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va
|
||||||
|
|
||||||
ValueVectorMap attrs;
|
ValueVectorMap attrs;
|
||||||
|
|
||||||
for (auto vElem : args[1]->listItems()) {
|
for (auto vElem : args[1]->listView()) {
|
||||||
Value res;
|
Value res;
|
||||||
state.callFunction(*args[0], *vElem, res, pos);
|
state.callFunction(*args[0], *vElem, res, pos);
|
||||||
auto name = state.forceStringNoCtx(res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy");
|
auto name = state.forceStringNoCtx(res, pos, "while evaluating the return value of the grouping function passed to builtins.groupBy");
|
||||||
|
@ -3900,7 +3903,7 @@ static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
for (size_t n = 0; n < nrLists; ++n) {
|
for (size_t n = 0; n < nrLists; ++n) {
|
||||||
Value * vElem = args[1]->listElems()[n];
|
Value * vElem = args[1]->listView()[n];
|
||||||
state.callFunction(*args[0], *vElem, lists[n], pos);
|
state.callFunction(*args[0], *vElem, lists[n], pos);
|
||||||
state.forceList(lists[n], lists[n].determinePos(args[0]->determinePos(pos)), "while evaluating the return value of the function passed to builtins.concatMap");
|
state.forceList(lists[n], lists[n].determinePos(args[0]->determinePos(pos)), "while evaluating the return value of the function passed to builtins.concatMap");
|
||||||
len += lists[n].listSize();
|
len += lists[n].listSize();
|
||||||
|
@ -3909,9 +3912,10 @@ static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args,
|
||||||
auto list = state.buildList(len);
|
auto list = state.buildList(len);
|
||||||
auto out = list.elems;
|
auto out = list.elems;
|
||||||
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
|
for (size_t n = 0, pos = 0; n < nrLists; ++n) {
|
||||||
auto l = lists[n].listSize();
|
auto listView = lists[n].listView();
|
||||||
|
auto l = listView.size();
|
||||||
if (l)
|
if (l)
|
||||||
memcpy(out + pos, lists[n].listElems(), l * sizeof(Value *));
|
memcpy(out + pos, listView.data(), l * sizeof(Value *));
|
||||||
pos += l;
|
pos += l;
|
||||||
}
|
}
|
||||||
v.mkList(list);
|
v.mkList(list);
|
||||||
|
@ -4587,7 +4591,7 @@ static void prim_concatStringsSep(EvalState & state, const PosIdx pos, Value * *
|
||||||
res.reserve((args[1]->listSize() + 32) * sep.size());
|
res.reserve((args[1]->listSize() + 32) * sep.size());
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
for (auto elem : args[1]->listItems()) {
|
for (auto elem : args[1]->listView()) {
|
||||||
if (first) first = false; else res += sep;
|
if (first) first = false; else res += sep;
|
||||||
res += *state.coerceToString(pos, *elem, context, "while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep");
|
res += *state.coerceToString(pos, *elem, context, "while evaluating one element of the list of strings to concat passed to builtins.concatStringsSep");
|
||||||
}
|
}
|
||||||
|
@ -4617,11 +4621,11 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
|
||||||
|
|
||||||
std::vector<std::string_view> from;
|
std::vector<std::string_view> from;
|
||||||
from.reserve(args[0]->listSize());
|
from.reserve(args[0]->listSize());
|
||||||
for (auto elem : args[0]->listItems())
|
for (auto elem : args[0]->listView())
|
||||||
from.emplace_back(state.forceString(*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
|
from.emplace_back(state.forceString(*elem, pos, "while evaluating one of the strings to replace passed to builtins.replaceStrings"));
|
||||||
|
|
||||||
std::unordered_map<size_t, std::string_view> cache;
|
std::unordered_map<size_t, std::string_view> cache;
|
||||||
auto to = args[1]->listItems();
|
auto to = args[1]->listView();
|
||||||
|
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
auto s = state.forceString(*args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings");
|
auto s = state.forceString(*args[2], context, pos, "while evaluating the third argument passed to builtins.replaceStrings");
|
||||||
|
@ -5050,7 +5054,7 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings)
|
||||||
|
|
||||||
/* 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. */
|
||||||
getBuiltins().payload.attrs->sort();
|
const_cast<Bindings *>(getBuiltins().attrs())->sort();
|
||||||
|
|
||||||
staticBaseEnv->sort();
|
staticBaseEnv->sort();
|
||||||
|
|
||||||
|
|
|
@ -312,7 +312,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
|
||||||
name
|
name
|
||||||
).atPos(i.pos).debugThrow();
|
).atPos(i.pos).debugThrow();
|
||||||
}
|
}
|
||||||
for (auto elem : attr->value->listItems()) {
|
for (auto elem : attr->value->listView()) {
|
||||||
auto outputName = state.forceStringNoCtx(*elem, attr->pos, "while evaluating an output name within a string context");
|
auto outputName = state.forceStringNoCtx(*elem, attr->pos, "while evaluating an output name within a string context");
|
||||||
context.emplace(NixStringContextElem::Built {
|
context.emplace(NixStringContextElem::Built {
|
||||||
.drvPath = makeConstantStorePathRef(namePath),
|
.drvPath = makeConstantStorePathRef(namePath),
|
||||||
|
|
|
@ -50,11 +50,13 @@ void printAmbiguous(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case nList:
|
case nList:
|
||||||
if (seen && v.listSize() && !seen->insert(v.listElems()).second)
|
/* Use pointer to the Value instead of pointer to the elements, because
|
||||||
|
that would need to explicitly handle the case of SmallList. */
|
||||||
|
if (seen && v.listSize() && !seen->insert(&v).second)
|
||||||
str << "«repeated»";
|
str << "«repeated»";
|
||||||
else {
|
else {
|
||||||
str << "[ ";
|
str << "[ ";
|
||||||
for (auto v2 : v.listItems()) {
|
for (auto v2 : v.listView()) {
|
||||||
if (v2)
|
if (v2)
|
||||||
printAmbiguous(*v2, symbols, str, seen, depth - 1);
|
printAmbiguous(*v2, symbols, str, seen, depth - 1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -415,8 +415,8 @@ private:
|
||||||
if (depth < options.maxDepth) {
|
if (depth < options.maxDepth) {
|
||||||
increaseIndent();
|
increaseIndent();
|
||||||
output << "[";
|
output << "[";
|
||||||
auto listItems = v.listItems();
|
auto listItems = v.listView();
|
||||||
auto prettyPrint = shouldPrettyPrintList(listItems);
|
auto prettyPrint = shouldPrettyPrintList(listItems.span());
|
||||||
|
|
||||||
size_t currentListItemsPrinted = 0;
|
size_t currentListItemsPrinted = 0;
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ json printValueAsJSON(EvalState & state, bool strict,
|
||||||
case nList: {
|
case nList: {
|
||||||
out = json::array();
|
out = json::array();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (auto elem : v.listItems()) {
|
for (auto elem : v.listView()) {
|
||||||
try {
|
try {
|
||||||
out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore));
|
out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore));
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
|
|
|
@ -114,7 +114,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||||
|
|
||||||
case nList: {
|
case nList: {
|
||||||
XMLOpenElement _(doc, "list");
|
XMLOpenElement _(doc, "list");
|
||||||
for (auto v2 : v.listItems())
|
for (auto v2 : v.listView())
|
||||||
printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos);
|
printValueAsXML(state, strict, location, *v2, doc, context, drvsSeen, pos);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,7 +289,7 @@ static Flake readFlake(
|
||||||
Explicit<bool> { state.forceBool(*setting.value, setting.pos, "") });
|
Explicit<bool> { state.forceBool(*setting.value, setting.pos, "") });
|
||||||
else if (setting.value->type() == nList) {
|
else if (setting.value->type() == nList) {
|
||||||
std::vector<std::string> ss;
|
std::vector<std::string> ss;
|
||||||
for (auto elem : setting.value->listItems()) {
|
for (auto elem : setting.value->listView()) {
|
||||||
if (elem->type() != nString)
|
if (elem->type() != nString)
|
||||||
state.error<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
|
state.error<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
|
||||||
state.symbols[setting.name], showType(*setting.value)).debugThrow();
|
state.symbols[setting.name], showType(*setting.value)).debugThrow();
|
||||||
|
|
|
@ -1265,7 +1265,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||||
} else if (v->type() == nList) {
|
} else if (v->type() == nList) {
|
||||||
attrs2["type"] = "strings";
|
attrs2["type"] = "strings";
|
||||||
XMLOpenElement m(xml, "meta", attrs2);
|
XMLOpenElement m(xml, "meta", attrs2);
|
||||||
for (auto elem : v->listItems()) {
|
for (auto elem : v->listView()) {
|
||||||
if (elem->type() != nString) continue;
|
if (elem->type() != nString) continue;
|
||||||
XMLAttrs attrs3;
|
XMLAttrs attrs3;
|
||||||
attrs3["value"] = elem->c_str();
|
attrs3["value"] = elem->c_str();
|
||||||
|
|
|
@ -46,7 +46,7 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
|
||||||
if (mirrorList->value->listSize() < 1)
|
if (mirrorList->value->listSize() < 1)
|
||||||
throw Error("mirror URL '%s' did not expand to anything", url);
|
throw Error("mirror URL '%s' did not expand to anything", url);
|
||||||
|
|
||||||
std::string mirror(state.forceString(*mirrorList->value->listElems()[0], noPos, "while evaluating the first available mirror"));
|
std::string mirror(state.forceString(*mirrorList->value->listView()[0], noPos, "while evaluating the first available mirror"));
|
||||||
return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1);
|
return mirror + (hasSuffix(mirror, "/") ? "" : "/") + s.substr(p + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ static int main_nix_prefetch_url(int argc, char * * argv)
|
||||||
state->forceList(*attr->value, noPos, "while evaluating the urls to prefetch");
|
state->forceList(*attr->value, noPos, "while evaluating the urls to prefetch");
|
||||||
if (attr->value->listSize() < 1)
|
if (attr->value->listSize() < 1)
|
||||||
throw Error("'urls' list is empty");
|
throw Error("'urls' list is empty");
|
||||||
url = state->forceString(*attr->value->listElems()[0], noPos, "while evaluating the first url from the urls list");
|
url = state->forceString(*attr->value->listView()[0], noPos, "while evaluating the first url from the urls list");
|
||||||
|
|
||||||
/* Extract the hash mode. */
|
/* Extract the hash mode. */
|
||||||
auto attr2 = v.attrs()->get(state->symbols.create("outputHashMode"));
|
auto attr2 = v.attrs()->get(state->symbols.create("outputHashMode"));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue