1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00

libexpr: Make constant Values global constants, move out of EvalState

These constant Values have no business being in the EvalState in the
first place. The ultimate goal is to get rid of the ugly `getBuiltins`
and its relience (in `createBaseEnv`) on these global constants is getting in the way.

Same idea as in f017f9ddd3.

Co-authored-by: eldritch horrors <pennae@lix.systems>
This commit is contained in:
Sergei Zimmerman 2025-09-11 01:53:41 +03:00
parent 462b9ac49c
commit 5db4b0699c
No known key found for this signature in database
7 changed files with 67 additions and 39 deletions

View file

@ -284,10 +284,6 @@ EvalState::EvalState(
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes"); static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
vEmptyList.mkList(buildList(0));
vNull.mkNull();
vTrue.mkBool(true);
vFalse.mkBool(false);
vStringRegular.mkStringNoCopy("regular"); vStringRegular.mkStringNoCopy("regular");
vStringDirectory.mkStringNoCopy("directory"); vStringDirectory.mkStringNoCopy("directory");
vStringSymlink.mkStringNoCopy("symlink"); vStringSymlink.mkStringNoCopy("symlink");
@ -894,7 +890,7 @@ ListBuilder::ListBuilder(EvalState & state, size_t size)
Value * EvalState::getBool(bool b) Value * EvalState::getBool(bool b)
{ {
return b ? &vTrue : &vFalse; return b ? &Value::vTrue : &Value::vFalse;
} }
unsigned long nrThunks = 0; unsigned long nrThunks = 0;
@ -1300,7 +1296,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v)
Value * ExprList::maybeThunk(EvalState & state, Env & env) Value * ExprList::maybeThunk(EvalState & state, Env & env)
{ {
if (elems.empty()) { if (elems.empty()) {
return &state.vEmptyList; return &Value::vEmptyList;
} }
return Expr::maybeThunk(state, env); return Expr::maybeThunk(state, env);
} }

View file

@ -313,32 +313,6 @@ public:
*/ */
RepairFlag repair; RepairFlag repair;
/**
* Empty list constant.
*/
Value vEmptyList;
/**
* `null` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
Value vNull;
/**
* `true` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
Value vTrue;
/**
* `true` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
Value vFalse;
/** `"regular"` */ /** `"regular"` */
Value vStringRegular; Value vStringRegular;
/** `"directory"` */ /** `"directory"` */

View file

@ -833,6 +833,34 @@ struct Value : public ValueStorage<sizeof(void *)>
{ {
friend std::string showType(const Value & v); friend std::string showType(const Value & v);
/**
* Empty list constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
static Value vEmptyList;
/**
* `null` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
static Value vNull;
/**
* `true` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
static Value vTrue;
/**
* `true` constant.
*
* This is _not_ a singleton. Pointer equality is _not_ sufficient.
*/
static Value vFalse;
private: private:
template<InternalType... discriminator> template<InternalType... discriminator>
bool isa() const noexcept bool isa() const noexcept

View file

@ -163,6 +163,7 @@ sources = files(
'search-path.cc', 'search-path.cc',
'value-to-json.cc', 'value-to-json.cc',
'value-to-xml.cc', 'value-to-xml.cc',
'value.cc',
'value/context.cc', 'value/context.cc',
) )

View file

@ -1075,11 +1075,11 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value ** args, Val
try { try {
state.forceValue(*args[0], pos); state.forceValue(*args[0], pos);
attrs.insert(state.s.value, args[0]); attrs.insert(state.s.value, args[0]);
attrs.insert(state.symbols.create("success"), &state.vTrue); attrs.insert(state.symbols.create("success"), &Value::vTrue);
} catch (AssertionError & e) { } catch (AssertionError & e) {
// `value = false;` is unfortunate but removing it is a breaking change. // `value = false;` is unfortunate but removing it is a breaking change.
attrs.insert(state.s.value, &state.vFalse); attrs.insert(state.s.value, &Value::vFalse);
attrs.insert(state.symbols.create("success"), &state.vFalse); attrs.insert(state.symbols.create("success"), &Value::vFalse);
} }
// restore the debugRepl pointer if we saved it earlier. // restore the debugRepl pointer if we saved it earlier.
@ -4613,7 +4613,7 @@ void prim_match(EvalState & state, const PosIdx pos, Value ** args, Value & v)
auto list = state.buildList(match.size() - 1); auto list = state.buildList(match.size() - 1);
for (const auto & [i, v2] : enumerate(list)) for (const auto & [i, v2] : enumerate(list))
if (!match[i + 1].matched) if (!match[i + 1].matched)
v2 = &state.vNull; v2 = &Value::vNull;
else else
v2 = mkString(state, match[i + 1]); v2 = mkString(state, match[i + 1]);
v.mkList(list); v.mkList(list);
@ -4705,7 +4705,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value ** args, Value & v)
auto list2 = state.buildList(slen); auto list2 = state.buildList(slen);
for (const auto & [si, v2] : enumerate(list2)) { for (const auto & [si, v2] : enumerate(list2)) {
if (!match[si + 1].matched) if (!match[si + 1].matched)
v2 = &state.vNull; v2 = &Value::vNull;
else else
v2 = mkString(state, match[si + 1]); v2 = mkString(state, match[si + 1]);
} }
@ -5059,7 +5059,7 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings)
addConstant( addConstant(
"null", "null",
&vNull, &Value::vNull,
{ {
.type = nNull, .type = nNull,
.doc = R"( .doc = R"(

29
src/libexpr/value.cc Normal file
View file

@ -0,0 +1,29 @@
#include "nix/expr/value.hh"
namespace nix {
Value Value::vEmptyList = []() {
Value res;
res.setStorage(List{.size = 0, .elems = nullptr});
return res;
}();
Value Value::vNull = []() {
Value res;
res.mkNull();
return res;
}();
Value Value::vTrue = []() {
Value res;
res.mkBool(true);
return res;
}();
Value Value::vFalse = []() {
Value res;
res.mkBool(false);
return res;
}();
} // namespace nix

View file

@ -158,7 +158,7 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v
directory). */ directory). */
else if (st.type == SourceAccessor::tDirectory) { else if (st.type == SourceAccessor::tDirectory) {
auto attrs = state.buildBindings(maxAttrs); auto attrs = state.buildBindings(maxAttrs);
attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList); attrs.insert(state.symbols.create("_combineChannels"), &Value::vEmptyList);
StringSet seen; StringSet seen;
getAllExprs(state, path, seen, attrs); getAllExprs(state, path, seen, attrs);
v.mkAttrs(attrs); v.mkAttrs(attrs);