diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b586c3409..3a53ecf79 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -284,10 +284,6 @@ EvalState::EvalState( 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"); vStringDirectory.mkStringNoCopy("directory"); vStringSymlink.mkStringNoCopy("symlink"); @@ -894,7 +890,7 @@ ListBuilder::ListBuilder(EvalState & state, size_t size) Value * EvalState::getBool(bool b) { - return b ? &vTrue : &vFalse; + return b ? &Value::vTrue : &Value::vFalse; } unsigned long nrThunks = 0; @@ -1300,7 +1296,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) Value * ExprList::maybeThunk(EvalState & state, Env & env) { if (elems.empty()) { - return &state.vEmptyList; + return &Value::vEmptyList; } return Expr::maybeThunk(state, env); } diff --git a/src/libexpr/include/nix/expr/eval.hh b/src/libexpr/include/nix/expr/eval.hh index 0b91645ea..430e334b8 100644 --- a/src/libexpr/include/nix/expr/eval.hh +++ b/src/libexpr/include/nix/expr/eval.hh @@ -313,32 +313,6 @@ public: */ 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"` */ Value vStringRegular; /** `"directory"` */ diff --git a/src/libexpr/include/nix/expr/value.hh b/src/libexpr/include/nix/expr/value.hh index 0b10b78b5..c74588a31 100644 --- a/src/libexpr/include/nix/expr/value.hh +++ b/src/libexpr/include/nix/expr/value.hh @@ -833,6 +833,34 @@ struct Value : public ValueStorage { 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: template bool isa() const noexcept diff --git a/src/libexpr/meson.build b/src/libexpr/meson.build index 00fb82e3c..40d3f390b 100644 --- a/src/libexpr/meson.build +++ b/src/libexpr/meson.build @@ -163,6 +163,7 @@ sources = files( 'search-path.cc', 'value-to-json.cc', 'value-to-xml.cc', + 'value.cc', 'value/context.cc', ) diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 2a3eec672..f099e060e 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1075,11 +1075,11 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value ** args, Val try { state.forceValue(*args[0], pos); 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) { // `value = false;` is unfortunate but removing it is a breaking change. - attrs.insert(state.s.value, &state.vFalse); - attrs.insert(state.symbols.create("success"), &state.vFalse); + attrs.insert(state.s.value, &Value::vFalse); + attrs.insert(state.symbols.create("success"), &Value::vFalse); } // 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); for (const auto & [i, v2] : enumerate(list)) if (!match[i + 1].matched) - v2 = &state.vNull; + v2 = &Value::vNull; else v2 = mkString(state, match[i + 1]); v.mkList(list); @@ -4705,7 +4705,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value ** args, Value & v) auto list2 = state.buildList(slen); for (const auto & [si, v2] : enumerate(list2)) { if (!match[si + 1].matched) - v2 = &state.vNull; + v2 = &Value::vNull; else v2 = mkString(state, match[si + 1]); } @@ -5059,7 +5059,7 @@ void EvalState::createBaseEnv(const EvalSettings & evalSettings) addConstant( "null", - &vNull, + &Value::vNull, { .type = nNull, .doc = R"( diff --git a/src/libexpr/value.cc b/src/libexpr/value.cc new file mode 100644 index 000000000..07d036b0d --- /dev/null +++ b/src/libexpr/value.cc @@ -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 diff --git a/src/nix/nix-env/nix-env.cc b/src/nix/nix-env/nix-env.cc index f165c069c..01c8ccf4b 100644 --- a/src/nix/nix-env/nix-env.cc +++ b/src/nix/nix-env/nix-env.cc @@ -158,7 +158,7 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v directory). */ else if (st.type == SourceAccessor::tDirectory) { auto attrs = state.buildBindings(maxAttrs); - attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList); + attrs.insert(state.symbols.create("_combineChannels"), &Value::vEmptyList); StringSet seen; getAllExprs(state, path, seen, attrs); v.mkAttrs(attrs);