From be3a40e5dc5d1b2e43d92490de7e85febdee665e Mon Sep 17 00:00:00 2001 From: skye Date: Mon, 23 Feb 2026 23:27:07 -0500 Subject: [PATCH] libexpr: Replace Value::mkString with constructor calls Change-Id: I55bba546eb090728a71734450a2a5f496a6a6964 --- lix/legacy/nix-env.cc | 6 +- lix/legacy/user-env.cc | 22 +++-- lix/libcmd/common-eval-args.cc | 2 +- lix/libcmd/repl.cc | 3 +- lix/libexpr/eval.cc | 22 +++-- lix/libexpr/flake/flake.cc | 8 +- lix/libexpr/json-to-value.cc | 2 +- lix/libexpr/primops.cc | 123 +++++++++++++++----------- lix/libexpr/primops/context.cc | 10 +-- lix/libexpr/primops/fetchMercurial.cc | 6 +- lix/libexpr/primops/fetchTree.cc | 21 +++-- lix/libexpr/primops/fromTOML.cc | 2 +- lix/libexpr/value.cc | 13 --- lix/libexpr/value.hh | 15 +++- lix/nix/main.cc | 3 +- tests/unit/libexpr/json.cc | 7 +- tests/unit/libexpr/value/print.cc | 21 ++--- 17 files changed, 147 insertions(+), 139 deletions(-) diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index 38455a08b..409e76470 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -151,8 +151,7 @@ static void getAllExprs(Evaluator & state, continue; } /* Load the expression on demand. */ - Value vArg; - vArg.mkString(path2.canonical().abs()); + Value vArg = {NewValueAs::string, path2.canonical().abs()}; if (seen.size() == maxAttrs) throw Error("too many Nix expressions in directory '%1%'", path); attrs.alloc(attrName @@ -516,8 +515,7 @@ static bool keep(EvalState & state, DrvInfo & drv) static void setMetaFlag(EvalState & state, DrvInfo & drv, const std::string & name, const std::string & value) { - Value v; - v.mkString(value); + Value v = {NewValueAs::string, value}; drv.setMeta(state, name, v); } diff --git a/lix/legacy/user-env.cc b/lix/legacy/user-env.cc index d4fe9f393..16eb57a75 100644 --- a/lix/legacy/user-env.cc +++ b/lix/legacy/user-env.cc @@ -46,25 +46,29 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, auto attrs = state.ctx.buildBindings(7 + outputs.size()); - attrs.alloc(state.ctx.symbols.sym_type).mkString("derivation"); - attrs.alloc(state.ctx.symbols.sym_name).mkString(i.queryName(state)); + attrs.alloc(state.ctx.symbols.sym_type) = {NewValueAs::string, "derivation"}; + attrs.alloc(state.ctx.symbols.sym_name) = {NewValueAs::string, i.queryName(state)}; auto system = i.querySystem(state); if (!system.empty()) - attrs.alloc(state.ctx.symbols.sym_system).mkString(system); - attrs.alloc(state.ctx.symbols.sym_outPath) - .mkString(state.ctx.store->printStorePath(i.queryOutPath(state))); + attrs.alloc(state.ctx.symbols.sym_system) = {NewValueAs::string, system}; + attrs.alloc(state.ctx.symbols.sym_outPath) = { + NewValueAs::string, state.ctx.store->printStorePath(i.queryOutPath(state)) + }; if (drvPath) - attrs.alloc(state.ctx.symbols.sym_drvPath).mkString(state.ctx.store->printStorePath(*drvPath)); + attrs.alloc(state.ctx.symbols.sym_drvPath) = { + NewValueAs::string, state.ctx.store->printStorePath(*drvPath) + }; // Copy each output meant for installation. auto & vOutputs = attrs.alloc(state.ctx.symbols.sym_outputs); auto outputsList = state.ctx.mem.newList(outputs.size()); vOutputs = {NewValueAs::list, outputsList}; for (const auto & [m, j] : enumerate(outputs)) { - outputsList->elems[m].mkString(j.first); + outputsList->elems[m] = {NewValueAs::string, j.first}; auto outputAttrs = state.ctx.buildBindings(2); - outputAttrs.alloc(state.ctx.symbols.sym_outPath) - .mkString(state.ctx.store->printStorePath(*j.second)); + outputAttrs.alloc(state.ctx.symbols.sym_outPath) = { + NewValueAs::string, state.ctx.store->printStorePath(*j.second) + }; attrs.alloc(j.first) = {NewValueAs::attrs, outputAttrs}; /* This is only necessary when installing store paths, e.g., diff --git a/lix/libcmd/common-eval-args.cc b/lix/libcmd/common-eval-args.cc index eee525ce6..a36bdcea6 100644 --- a/lix/libcmd/common-eval-args.cc +++ b/lix/libcmd/common-eval-args.cc @@ -189,7 +189,7 @@ Bindings * MixEvalArgs::getAutoArgs(Evaluator & state) state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd()), v ); else - v.mkString(((std::string_view) i.second).substr(1)); + v = {NewValueAs::string, ((std::string_view) i.second).substr(1)}; res.insert(state.symbols.create(i.first), v); } return res.finish(); diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index 5315c496c..34a0947a0 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -1496,8 +1496,7 @@ Value NixRepl::replInitInfo() { auto builder = evaluator.buildBindings(2); - Value currentSystem; - currentSystem.mkString(evalSettings.getCurrentSystem()); + Value currentSystem = {NewValueAs::string, evalSettings.getCurrentSystem()}; builder.insert(evaluator.symbols.create("currentSystem"), currentSystem); return {NewValueAs::attrs, builder.finish()}; diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 4040ec2d3..71a760ef5 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -857,7 +857,7 @@ void EvalState::mkPos(Value & v, PosIdx p) auto origin = ctx.positions.originOf(p); if (auto path = std::get_if(&origin)) { auto attrs = ctx.buildBindings(3); - attrs.alloc(ctx.symbols.sym_file).mkString(path->to_string()); + attrs.alloc(ctx.symbols.sym_file) = {NewValueAs::string, path->to_string()}; makePositionThunks(*this, p, attrs.alloc(ctx.symbols.sym_line), attrs.alloc(ctx.symbols.sym_column)); v = {NewValueAs::attrs, attrs}; } else @@ -867,11 +867,13 @@ void EvalState::mkPos(Value & v, PosIdx p) void EvalPaths::mkStorePathString(const StorePath & p, Value & v) { - v.mkString( + v = { + NewValueAs::string, store->printStorePath(p), - NixStringContext { - NixStringContextElem::Opaque { .path = p }, - }); + NixStringContext{ + NixStringContextElem::Opaque{.path = p}, + } + }; } @@ -887,7 +889,7 @@ void EvalState::mkOutputString( const SingleDerivedPath::Built & b, const StorePath & staticOutputPath) { - value.mkString(mkOutputStringRaw(staticOutputPath), NixStringContext { b }); + value = {NewValueAs::string, mkOutputStringRaw(staticOutputPath), NixStringContext{b}}; } @@ -914,11 +916,13 @@ void EvalState::mkSingleDerivedPathString( const SingleDerivedPath & p, Value & v) { - v.mkString( + v = { + NewValueAs::string, mkSingleDerivedPathStringRaw(p), - NixStringContext { + NixStringContext{ std::visit([](auto && v) -> NixStringContextElem { return v; }, p), - }); + } + }; } struct CachedEvalFile diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index b11792656..2580aea6e 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -948,7 +948,7 @@ void callFlake(EvalState & state, Value vRootSrc; Value vRootSubdir; - vLocks.mkString(lockedFlake.lockFile.to_string()); + vLocks = {NewValueAs::string, lockedFlake.lockFile.to_string()}; emitTreeAttrs( state.ctx, @@ -959,7 +959,7 @@ void callFlake(EvalState & state, lockedFlake.flake.forceDirty ); - vRootSubdir.mkString(lockedFlake.flake.lockedRef.subdir); + vRootSubdir = {NewValueAs::string, lockedFlake.flake.lockedRef.subdir}; if (!state.ctx.caches.vCallFlake) { state.ctx.caches.vCallFlake = allocRootValue({}); @@ -1006,7 +1006,7 @@ void prim_parseFlakeRef( auto & vv = binds.alloc(s); std::visit( overloaded{ - [&vv](const std::string & value) { vv.mkString(value); }, + [&vv](const std::string & value) { vv = {NewValueAs::string, value}; }, [&vv](const uint64_t & value) { vv = {NewValueAs::integer, NixInt::Inner(value)}; }, [&vv](const Explicit & value) { vv = {NewValueAs::boolean, value.t}; } }, @@ -1051,7 +1051,7 @@ void prim_flakeRefToString( } } auto flakeRef = FlakeRef::fromAttrs(attrs); - v.mkString(flakeRef.to_string()); + v = {NewValueAs::string, flakeRef.to_string()}; } } diff --git a/lix/libexpr/json-to-value.cc b/lix/libexpr/json-to-value.cc index ef9885d90..00cea5b5b 100644 --- a/lix/libexpr/json-to-value.cc +++ b/lix/libexpr/json-to-value.cc @@ -135,7 +135,7 @@ public: bool string(string_t & val) override { - rs->value().mkString(val); + rs->value() = {NewValueAs::string, val}; rs->add(); return true; } diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 89b398a59..36b7ea240 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -180,21 +180,21 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v) if (auto storePath = isValidDerivationInStore()) { Derivation drv = state.aio.blockOn(state.ctx.store->readDerivation(*storePath)); auto attrs = state.ctx.buildBindings(3 + drv.outputs.size()); - attrs.alloc(state.ctx.symbols.sym_drvPath) - .mkString( - path2, - { - NixStringContextElem::DrvDeep{.drvPath = *storePath}, - } - ); - attrs.alloc(state.ctx.symbols.sym_name).mkString(drv.env["name"]); + attrs.alloc(state.ctx.symbols.sym_drvPath) = { + NewValueAs::string, + path2, + { + NixStringContextElem::DrvDeep{.drvPath = *storePath}, + } + }; + attrs.alloc(state.ctx.symbols.sym_name) = {NewValueAs::string, drv.env["name"]}; auto & outputsVal = attrs.alloc(state.ctx.symbols.sym_outputs); auto outputsList = state.ctx.mem.newList(drv.outputs.size()); outputsVal = {NewValueAs::list, outputsList}; for (const auto & [i, o] : enumerate(drv.outputs)) { mkOutputString(state, attrs, *storePath, o); - outputsList->elems[i].mkString(o.first); + outputsList->elems[i] = {NewValueAs::string, o.first}; } Value w{NewValueAs::attrs, attrs.finish()}; @@ -372,7 +372,7 @@ static void prim_typeOf(EvalState & state, Value * * args, Value & v) case nFloat: t = "float"; break; case nThunk: abort(); } - v.mkString(t); + v = {NewValueAs::string, t}; } /* Determine whether the argument is the null value. */ @@ -735,7 +735,10 @@ static void prim_tryEval(EvalState & state, Value * * args, Value & v) static void prim_getEnv(EvalState & state, Value * * args, Value & v) { std::string name(state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.getEnv")); - v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or("")); + v = { + NewValueAs::string, + evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or("") + }; } /* Evaluate the first argument, then return the second argument. */ @@ -1253,13 +1256,13 @@ drvName, Bindings * attrs, Value & v) } auto result = state.ctx.buildBindings(1 + drv.outputs.size()); - result.alloc(state.ctx.symbols.sym_drvPath) - .mkString( - drvPathS, - { - NixStringContextElem::DrvDeep{.drvPath = drvPath}, - } - ); + result.alloc(state.ctx.symbols.sym_drvPath) = { + NewValueAs::string, + drvPathS, + { + NixStringContextElem::DrvDeep{.drvPath = drvPath}, + } + }; for (auto & i : drv.outputs) mkOutputString(state, result, drvPath, i); @@ -1275,7 +1278,12 @@ drvName, Bindings * attrs, Value & v) ‘out’. */ static void prim_placeholder(EvalState & state, Value * * args, Value & v) { - v.mkString(hashPlaceholder(state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.placeholder"))); + v = { + NewValueAs::string, + hashPlaceholder(state.forceStringNoCtx( + *args[0], noPos, "while evaluating the first argument passed to builtins.placeholder" + )) + }; } @@ -1289,7 +1297,7 @@ static void prim_toPath(EvalState & state, Value * * args, Value & v) { NixStringContext context; auto path = state.coerceToPath(noPos, *args[0], context, "while evaluating the first argument passed to builtins.toPath"); - v.mkString(path.to_string(), context); + v = {NewValueAs::string, path.to_string(), context}; } /* Allow a valid store path to be used in an expression. This is @@ -1322,7 +1330,7 @@ static void prim_storePath(EvalState & state, Value * * args, Value & v) if (!settings.readOnlyMode) state.aio.blockOn(state.ctx.store->ensurePath(path2)); context.insert(NixStringContextElem::Opaque { .path = path2 }); - v.mkString(path.abs(), context); + v = {NewValueAs::string, path.abs(), context}; } static void prim_pathExists(EvalState & state, Value * * args, Value & v) @@ -1365,9 +1373,18 @@ static void prim_pathExists(EvalState & state, Value * * args, Value & v) static void prim_baseNameOf(EvalState & state, Value * * args, Value & v) { NixStringContext context; - v.mkString(baseNameOf(*state.coerceToString(noPos, *args[0], context, + v = { + NewValueAs::string, + baseNameOf(*state.coerceToString( + noPos, + *args[0], + context, "while evaluating the first argument passed to builtins.baseNameOf", - StringCoercionMode::Strict, false)), context); + StringCoercionMode::Strict, + false + )), + context + }; } /* Return the directory of the given path, i.e., everything before the @@ -1385,7 +1402,7 @@ static void prim_dirOf(EvalState & state, Value * * args, Value & v) "while evaluating the first argument passed to 'builtins.dirOf'", StringCoercionMode::Strict, false); auto dir = dirOf(*path); - v.mkString(dir, context); + v = {NewValueAs::string, dir, context}; } } @@ -1415,7 +1432,7 @@ static void prim_readFile(EvalState & state, Value * * args, Value & v) .path = std::move((StorePath &&)p), }); } - v.mkString(s, context); + v = {NewValueAs::string, s, context}; } /* Find a file in the Nix search path. Used to implement paths, @@ -1494,7 +1511,7 @@ static void prim_hashFile(EvalState & state, Value * * args, Value & v) auto path = realisePath(state, *args[1]); - v.mkString(hashString(*ht, path.readFile()).to_string(HashFormat::Base16, false)); + v = {NewValueAs::string, hashString(*ht, path.readFile()).to_string(HashFormat::Base16, false)}; } static std::string_view fileTypeToString(InputAccessor::Type type) @@ -1510,7 +1527,7 @@ static void prim_readFileType(EvalState & state, Value * * args, Value & v) { auto path = realisePath(state, *args[0]); /* Retrieve the directory entry type and stringize it. */ - v.mkString(fileTypeToString(path.lstat().type)); + v = {NewValueAs::string, fileTypeToString(path.lstat().type)}; } /* Read a directory (without . or ..) */ @@ -1543,7 +1560,7 @@ static void prim_readDir(EvalState & state, Value * * args, Value & v) } else { // This branch of the conditional is much more likely. // Here we just stringize the directory entry type. - attr.mkString(fileTypeToString(*type)); + attr = {NewValueAs::string, fileTypeToString(*type)}; } } @@ -1563,7 +1580,7 @@ static void prim_toXML(EvalState & state, Value * * args, Value & v) std::ostringstream out; NixStringContext context; printValueAsXML(state, true, false, *args[0], out, context, noPos); - v.mkString(out.str(), context); + v = {NewValueAs::string, out.str(), context}; } /* Convert the argument (which can be any Nix expression) to a JSON @@ -1574,7 +1591,7 @@ static void prim_toJSON(EvalState & state, Value * * args, Value & v) std::ostringstream out; NixStringContext context; printValueAsJSON(state, true, *args[0], noPos, out, context); - v.mkString(out.str(), context); + v = {NewValueAs::string, out.str(), context}; } /* Parse a JSON string to a value. */ @@ -1666,16 +1683,16 @@ static void addPath( the second is a string indicating the type of the file. */ Value arg1; if (isInDir(p, realPath)) - arg1.mkString(path + "/" + std::string(p, realPath.size() + 1)); + arg1 = {NewValueAs::string, path + "/" + std::string(p, realPath.size() + 1)}; else - arg1.mkString(p); + arg1 = {NewValueAs::string, p}; - Value arg2; - arg2.mkString( - S_ISREG(st.st_mode) ? "regular" : - S_ISDIR(st.st_mode) ? "directory" : - S_ISLNK(st.st_mode) ? "symlink" : - "unknown" /* not supported, will fail! */); + Value arg2 = + {NewValueAs::string, + S_ISREG(st.st_mode) ? "regular" + : S_ISDIR(st.st_mode) ? "directory" + : S_ISLNK(st.st_mode) ? "symlink" + : "unknown" /* not supported, will fail! */}; Value args[]{arg1, arg2}; Value res = state.callFunction(*filterFun, args, noPos); @@ -2714,7 +2731,7 @@ static void prim_toString(EvalState & state, Value * * args, Value & v) auto s = state.coerceToString(noPos, *args[0], context, "while evaluating the first argument passed to builtins.toString", StringCoercionMode::ToString, false); - v.mkString(*s, context); + v = {NewValueAs::string, *s, context}; } /* `substring start len str' returns the substring of `str' starting @@ -2743,7 +2760,7 @@ static void prim_substring(EvalState & state, Value * * args, Value & v) if (len_arg == 0) { state.forceValue(*args[2], noPos); if (args[2]->type() == nString) { - v.mkString("", args[2]->string().context); + v = Value{NewValueAs::string, "", args[2]->string().context}; return; } } @@ -2763,7 +2780,7 @@ static void prim_substring(EvalState & state, Value * * args, Value & v) auto len = len_arg >= 0 ? std::min(static_cast(s->size()), NixUInt(len_arg)) : std::numeric_limits::max(); - v.mkString(NixUInt(start) >= s->size() ? "" : s->substr(start, len), context); + v = {NewValueAs::string, NixUInt(start) >= s->size() ? "" : s->substr(start, len), context}; } static void prim_stringLength(EvalState & state, Value * * args, Value & v) @@ -2784,7 +2801,7 @@ static void prim_hashString(EvalState & state, Value * * args, Value & v) NixStringContext context; // discarded auto s = state.forceString(*args[1], context, noPos, "while evaluating the second argument passed to builtins.hashString"); - v.mkString(hashString(*ht, s).to_string(HashFormat::Base16, false)); + v = {NewValueAs::string, hashString(*ht, s).to_string(HashFormat::Base16, false)}; } struct RegexCache @@ -2836,7 +2853,7 @@ void prim_match(EvalState & state, Value * * args, Value & v) if (!match[i+1].matched) result->elems[i].mkNull(); else - result->elems[i].mkString(match[i + 1].str()); + result->elems[i] = {NewValueAs::string, match[i + 1].str()}; } } catch (regex::Error & e) { @@ -2876,7 +2893,7 @@ void prim_split(EvalState & state, Value * * args, Value & v) auto match = *i; // Add a string for non-matched characters. - result->elems[idx++].mkString(match.prefix().str()); + result->elems[idx++] = {NewValueAs::string, match.prefix().str()}; // Add a list for matched substrings. const size_t slen = match.size() - 1; @@ -2889,12 +2906,12 @@ void prim_split(EvalState & state, Value * * args, Value & v) if (!match[si + 1].matched) content->elems[si].mkNull(); else - content->elems[si].mkString(match[si + 1].str()); + content->elems[si] = {NewValueAs::string, match[si + 1].str()}; } // Add a string for non-matched suffix characters. if (idx == 2 * len) { - result->elems[idx++].mkString(match.suffix().str()); + result->elems[idx++] = {NewValueAs::string, match.suffix().str()}; } } @@ -2927,7 +2944,7 @@ static void prim_concatStringsSep(EvalState & state, Value * * args, Value & v) ); } - v.mkString(res, context); + v = {NewValueAs::string, res, context}; } static void prim_replaceStrings(EvalState & state, Value * * args, Value & v) @@ -2997,7 +3014,7 @@ static void prim_replaceStrings(EvalState & state, Value * * args, Value & v) } } - v.mkString(res, context); + v = {NewValueAs::string, res, context}; } @@ -3011,8 +3028,8 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v) auto name = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.parseDrvName"); DrvName parsed(name); auto attrs = state.ctx.buildBindings(2); - attrs.alloc(state.ctx.symbols.sym_name).mkString(parsed.name); - attrs.alloc("version").mkString(parsed.version); + attrs.alloc(state.ctx.symbols.sym_name) = {NewValueAs::string, parsed.name}; + attrs.alloc("version") = {NewValueAs::string, parsed.version}; v = {NewValueAs::attrs, attrs}; } @@ -3038,7 +3055,7 @@ static void prim_splitVersion(EvalState & state, Value * * args, Value & v) auto result = state.ctx.mem.newList(components.size()); v = {NewValueAs::list, result}; for (const auto & [n, component] : enumerate(components)) - result->elems[n].mkString(std::move(component)); + result->elems[n] = {NewValueAs::string, component}; } @@ -3061,8 +3078,8 @@ Value EvalBuiltins::prepareNixPath(const SearchPath & searchPath) int n = 0; for (auto & i : searchPath.elements) { auto attrs = mem.buildBindings(symbols, 2); - attrs.alloc("path").mkString(i.path.s); - attrs.alloc("prefix").mkString(i.prefix.s); + attrs.alloc("path") = {NewValueAs::string, i.path.s}; + attrs.alloc("prefix") = {NewValueAs::string, i.prefix.s}; v->elems[n++] = {NewValueAs::attrs, attrs}; } return {NewValueAs::list, v}; diff --git a/lix/libexpr/primops/context.cc b/lix/libexpr/primops/context.cc index 2e711c9ee..d430fd9e3 100644 --- a/lix/libexpr/primops/context.cc +++ b/lix/libexpr/primops/context.cc @@ -11,7 +11,7 @@ void prim_unsafeDiscardStringContext(EvalState & state, Value ** args, Value & v { NixStringContext context; auto s = state.coerceToString(noPos, *args[0], context, "while evaluating the argument passed to builtins.unsafeDiscardStringContext"); - v.mkString(*s); + v = {NewValueAs::string, *s}; } void prim_hasContext(EvalState & state, Value * * args, Value & v) @@ -39,7 +39,7 @@ void prim_unsafeDiscardOutputDependency(EvalState & state, Value * * args, Value } } - v.mkString(*s, context2); + v = {NewValueAs::string, *s, context2}; } @@ -82,7 +82,7 @@ void prim_addDrvOutputDependencies(EvalState & state, Value * * args, Value & v) }, context.begin()->raw) }), }; - v.mkString(*s, context2); + v = {NewValueAs::string, *s, context2}; } @@ -144,7 +144,7 @@ void prim_getContext(EvalState & state, Value * * args, Value & v) auto content = state.ctx.mem.newList(info.second.outputs.size()); outputsVal = {NewValueAs::list, content}; for (const auto & [i, output] : enumerate(info.second.outputs)) - content->elems[i].mkString(output); + content->elems[i] = {NewValueAs::string, output}; } attrs.alloc(state.ctx.store->printStorePath(info.first)) = {NewValueAs::attrs, infoAttrs}; } @@ -232,6 +232,6 @@ void prim_appendContext(EvalState & state, Value ** args, Value & v) } } - v.mkString(orig, context); + v = {NewValueAs::string, orig, context}; } } diff --git a/lix/libexpr/primops/fetchMercurial.cc b/lix/libexpr/primops/fetchMercurial.cc index d3f51d0dc..8807e1406 100644 --- a/lix/libexpr/primops/fetchMercurial.cc +++ b/lix/libexpr/primops/fetchMercurial.cc @@ -90,12 +90,12 @@ void prim_fetchMercurial(EvalState & state, Value ** args, Value & v) auto attrs2 = state.ctx.buildBindings(8); state.ctx.paths.mkStorePathString(tree.storePath, attrs2.alloc(state.ctx.symbols.sym_outPath)); if (input2.getRef()) - attrs2.alloc("branch").mkString(*input2.getRef()); + attrs2.alloc("branch") = {NewValueAs::string, *input2.getRef()}; // Backward compatibility: set 'rev' to // 0000000000000000000000000000000000000000 for a dirty tree. auto rev2 = input2.getRev().value_or(Hash(HashType::SHA1)); - attrs2.alloc("rev").mkString(rev2.gitRev()); - attrs2.alloc("shortRev").mkString(rev2.gitRev().substr(0, 12)); + attrs2.alloc("rev") = {NewValueAs::string, rev2.gitRev()}; + attrs2.alloc("shortRev") = {NewValueAs::string, rev2.gitRev().substr(0, 12)}; if (auto revCount = input2.getRevCount()) attrs2.alloc("revCount") = {NewValueAs::integer, NixInt::Inner(*revCount)}; v = {NewValueAs::attrs, attrs2}; diff --git a/lix/libexpr/primops/fetchTree.cc b/lix/libexpr/primops/fetchTree.cc index 3ba1c2f06..ddba5567a 100644 --- a/lix/libexpr/primops/fetchTree.cc +++ b/lix/libexpr/primops/fetchTree.cc @@ -32,7 +32,7 @@ void emitTreeAttrs( auto narHash = input.getNarHash(); assert(narHash); - attrs.alloc("narHash").mkString(narHash->to_string()); + attrs.alloc("narHash") = {NewValueAs::string, narHash->to_string()}; if (input.getType() == "git") attrs.alloc("submodules") = { @@ -42,13 +42,13 @@ void emitTreeAttrs( if (!forceDirty) { if (auto rev = input.getRev()) { - attrs.alloc("rev").mkString(rev->gitRev()); - attrs.alloc("shortRev").mkString(rev->gitShortRev()); + attrs.alloc("rev") = {NewValueAs::string, rev->gitRev()}; + attrs.alloc("shortRev") = {NewValueAs::string, rev->gitShortRev()}; } else if (emptyRevFallback) { // Backwards compat for `builtins.fetchGit`: dirty repos return an empty sha1 as rev auto emptyHash = Hash(HashType::SHA1); - attrs.alloc("rev").mkString(emptyHash.gitRev()); - attrs.alloc("shortRev").mkString(emptyHash.gitShortRev()); + attrs.alloc("rev") = {NewValueAs::string, emptyHash.gitRev()}; + attrs.alloc("shortRev") = {NewValueAs::string, emptyHash.gitShortRev()}; } if (auto revCount = input.getRevCount()) @@ -58,14 +58,17 @@ void emitTreeAttrs( } if (auto dirtyRev = fetchers::maybeGetStrAttr(input.attrs, "dirtyRev")) { - attrs.alloc("dirtyRev").mkString(*dirtyRev); - attrs.alloc("dirtyShortRev").mkString(*fetchers::maybeGetStrAttr(input.attrs, "dirtyShortRev")); + attrs.alloc("dirtyRev") = {NewValueAs::string, *dirtyRev}; + attrs.alloc("dirtyShortRev") = { + NewValueAs::string, *fetchers::maybeGetStrAttr(input.attrs, "dirtyShortRev") + }; } if (auto lastModified = input.getLastModified()) { attrs.alloc("lastModified") = {NewValueAs::integer, *lastModified}; - attrs.alloc("lastModifiedDate").mkString( - fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S"))); + attrs.alloc("lastModifiedDate") = { + NewValueAs::string, fmt("%s", std::put_time(std::gmtime(&*lastModified), "%Y%m%d%H%M%S")) + }; } v = {NewValueAs::attrs, attrs}; diff --git a/lix/libexpr/primops/fromTOML.cc b/lix/libexpr/primops/fromTOML.cc index a83625cd0..28174c8b3 100644 --- a/lix/libexpr/primops/fromTOML.cc +++ b/lix/libexpr/primops/fromTOML.cc @@ -47,7 +47,7 @@ void prim_fromTOML(EvalState & state, Value ** args, Value & val) v = {NewValueAs::floating, toml::get(t)}; break; case toml::value_t::string: - v.mkString(toml::get(t)); + v = {NewValueAs::string, toml::get(t)}; break; case toml::value_t::local_datetime: case toml::value_t::offset_datetime: diff --git a/lix/libexpr/value.cc b/lix/libexpr/value.cc index c720ea1bc..868692355 100644 --- a/lix/libexpr/value.cc +++ b/lix/libexpr/value.cc @@ -61,19 +61,6 @@ void Value::mkPrimOp(PrimOp * p) *this = {NewValueAs::primop, *p}; } -void Value::mkString(std::string_view s, const char ** context) -{ - auto block = gcAllocType(); - *block = {.content = Str::gcCopy(s), .context = context}; - raw = tag(tString, block); -} - -void Value::mkString(std::string_view s, const NixStringContext & context) -{ - mkString(s); - copyContextToValue(*untag(), context); -} - Value::Value(string_t, Str * s, const NixStringContext & context) { auto block = gcAllocType(); diff --git a/lix/libexpr/value.hh b/lix/libexpr/value.hh index ff613269b..52dc94138 100644 --- a/lix/libexpr/value.hh +++ b/lix/libexpr/value.hh @@ -459,6 +459,17 @@ public: Value(string_t, const String * str) : raw(tag(tString, str)) {} + /// Constructx a nix language value of type "string", with a copy of the + /// string data viewed by @ref copyFrom and context from contextPtr. + /// + /// The string data *is* copied from @ref copyFrom, and this constructor + /// performs a dynamic (GC) allocation to do so, but contextPtr is used + /// as-is without copying, and must have been allocated ahead of time. + Value(string_t, std::string_view copyFrom, char const ** contextPtr) + : Value(NewValueAs::string, Str::gcCopy(copyFrom), contextPtr) + { + } + /// Constructx a nix language value of type "string", with a copy of the /// string data viewed by @ref copyFrom. /// @@ -775,10 +786,6 @@ public: */ inline ValueType type(bool invalidIsThunk = false) const; - void mkString(std::string_view s, const char ** context = 0); - - void mkString(std::string_view s, const NixStringContext & context); - inline void mkNull() { *this = {NewValueAs::null}; diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 9cc2b53ed..5e23f9b2a 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -365,8 +365,7 @@ static void showHelp(AsyncIoRoot & aio, std::vector subcommand, Nix , CanonPath::root )); - Value vDump; - vDump.mkString(toplevel.dumpCli()); + Value vDump = {NewValueAs::string, toplevel.dumpCli()}; Value vRes = state->callFunction(vGenerateManpage, evaluator.builtins.get("false"), noPos); vRes = state->callFunction(vRes, vDump, noPos); diff --git a/tests/unit/libexpr/json.cc b/tests/unit/libexpr/json.cc index 9d9bf3e56..a0e704042 100644 --- a/tests/unit/libexpr/json.cc +++ b/tests/unit/libexpr/json.cc @@ -41,15 +41,12 @@ namespace nix { } TEST_F(JSONValueTest, String) { - Value v; - v.mkString("test"); + Value v = {NewValueAs::string, "test"}; ASSERT_EQ(getJSONValue(v), "\"test\""); } TEST_F(JSONValueTest, StringQuotes) { - Value v; - - v.mkString("test\""); + Value v = {NewValueAs::string, "test\""}; ASSERT_EQ(getJSONValue(v), "\"test\\\"\""); } diff --git a/tests/unit/libexpr/value/print.cc b/tests/unit/libexpr/value/print.cc index 24d21516c..98b9c71a2 100644 --- a/tests/unit/libexpr/value/print.cc +++ b/tests/unit/libexpr/value/print.cc @@ -37,8 +37,7 @@ TEST_F(ValuePrintingTests, tBool) TEST_F(ValuePrintingTests, tString) { - Value vString; - vString.mkString("some-string"); + Value vString = {NewValueAs::string, "some-string"}; test(vString, "\"some-string\""); } @@ -260,8 +259,7 @@ struct StringPrintingTests : LibExprTest template void test(std::string_view literal, std::string_view expected, unsigned int maxLength, A... args) { - Value v; - v.mkString(literal); + Value v = {NewValueAs::string, literal}; std::stringstream out; printValue(state, out, v, PrintOptions { @@ -284,11 +282,9 @@ TEST_F(StringPrintingTests, maxLengthTruncation) // first, but only reorder the attrs when we have a maxAttrs budget. TEST_F(ValuePrintingTests, attrsTypeFirst) { - Value vType; - vType.mkString("puppy"); + Value vType = {NewValueAs::string, "puppy"}; - Value vApple; - vApple.mkString("apple"); + Value vApple = {NewValueAs::string, "apple"}; BindingsBuilder builder = evaluator.buildBindings(10); builder.insert(evaluator.symbols.create("type"), vType); @@ -342,8 +338,7 @@ TEST_F(ValuePrintingTests, ansiColorsBool) TEST_F(ValuePrintingTests, ansiColorsString) { - Value v; - v.mkString("puppy"); + Value v = {NewValueAs::string, "puppy"}; test(v, ANSI_MAGENTA "\"puppy\"" ANSI_NORMAL, @@ -354,8 +349,7 @@ TEST_F(ValuePrintingTests, ansiColorsString) TEST_F(ValuePrintingTests, ansiColorsStringElided) { - Value v; - v.mkString("puppy"); + Value v = {NewValueAs::string, "puppy"}; test(v, ANSI_MAGENTA "\"pup\" " ANSI_FAINT "«2 bytes elided»" ANSI_NORMAL, @@ -409,8 +403,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrs) TEST_F(ValuePrintingTests, ansiColorsDerivation) { - Value vDerivation; - vDerivation.mkString("derivation"); + Value vDerivation = {NewValueAs::string, "derivation"}; BindingsBuilder builder = evaluator.buildBindings(10); builder.insert(evaluator.symbols.sym_type, vDerivation);