libexpr: Replace StaticSymbols with NixSymbolTable

That struct has been annoying me since I've encountered it. There is no
reason for having to track all these symbols out of band in the state.

Change-Id: I5c2c0d8174af0a51f9b456cc3651d8203a406d09
This commit is contained in:
piegames
2026-01-03 13:19:55 +01:00
parent eac96ef6b5
commit d387c9113c
19 changed files with 183 additions and 225 deletions
+12 -10
View File
@@ -46,23 +46,25 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
auto attrs = state.ctx.buildBindings(7 + outputs.size());
attrs.alloc(state.ctx.s.type).mkString("derivation");
attrs.alloc(state.ctx.s.name).mkString(i.queryName(state));
attrs.alloc(state.ctx.symbols.sym_type).mkString("derivation");
attrs.alloc(state.ctx.symbols.sym_name).mkString(i.queryName(state));
auto system = i.querySystem(state);
if (!system.empty())
attrs.alloc(state.ctx.s.system).mkString(system);
attrs.alloc(state.ctx.s.outPath).mkString(state.ctx.store->printStorePath(i.queryOutPath(state)));
attrs.alloc(state.ctx.symbols.sym_system).mkString(system);
attrs.alloc(state.ctx.symbols.sym_outPath)
.mkString(state.ctx.store->printStorePath(i.queryOutPath(state)));
if (drvPath)
attrs.alloc(state.ctx.s.drvPath).mkString(state.ctx.store->printStorePath(*drvPath));
attrs.alloc(state.ctx.symbols.sym_drvPath).mkString(state.ctx.store->printStorePath(*drvPath));
// Copy each output meant for installation.
auto & vOutputs = attrs.alloc(state.ctx.s.outputs);
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);
auto outputAttrs = state.ctx.buildBindings(2);
outputAttrs.alloc(state.ctx.s.outPath).mkString(state.ctx.store->printStorePath(*j.second));
outputAttrs.alloc(state.ctx.symbols.sym_outPath)
.mkString(state.ctx.store->printStorePath(*j.second));
attrs.alloc(j.first).mkAttrs(outputAttrs);
/* This is only necessary when installing store paths, e.g.,
@@ -81,7 +83,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
meta.insert(state.ctx.symbols.create(j), *v);
}
attrs.alloc(state.ctx.s.meta).mkAttrs(meta);
attrs.alloc(state.ctx.symbols.sym_meta).mkAttrs(meta);
manifest->elems[n++].mkAttrs(attrs);
@@ -116,9 +118,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
debug("evaluating user environment builder");
state.forceValue(topLevel, noPos);
NixStringContext context;
const Attr & aDrvPath(*topLevel.attrs()->get(state.ctx.s.drvPath));
const Attr & aDrvPath(*topLevel.attrs()->get(state.ctx.symbols.sym_drvPath));
auto topLevelDrv = state.coerceToStorePath(aDrvPath.pos, aDrvPath.value, context, "");
const Attr & aOutPath(*topLevel.attrs()->get(state.ctx.s.outPath));
const Attr & aOutPath(*topLevel.attrs()->get(state.ctx.symbols.sym_outPath));
auto topLevelOut = state.coerceToStorePath(aOutPath.pos, aOutPath.value, context, "");
/* Realise the resulting store expression. */
+19 -72
View File
@@ -231,62 +231,6 @@ void initLibExpr()
libexprInitialised = true;
}
StaticSymbols::StaticSymbols(SymbolTable & symbols)
: outPath(symbols.create("outPath"))
, drvPath(symbols.create("drvPath"))
, type(symbols.create("type"))
, meta(symbols.create("meta"))
, name(symbols.create("name"))
, value(symbols.create("value"))
, system(symbols.create("system"))
, overrides(symbols.create("__overrides"))
, outputs(symbols.create("outputs"))
, outputName(symbols.create("outputName"))
, ignoreNulls(symbols.create("__ignoreNulls"))
, file(symbols.create("file"))
, line(symbols.create("line"))
, column(symbols.create("column"))
, functor(symbols.create("__functor"))
, toString(symbols.create("__toString"))
, right(symbols.create("right"))
, wrong(symbols.create("wrong"))
, structuredAttrs(symbols.create("__structuredAttrs"))
, allowedReferences(symbols.create("allowedReferences"))
, allowedRequisites(symbols.create("allowedRequisites"))
, disallowedReferences(symbols.create("disallowedReferences"))
, disallowedRequisites(symbols.create("disallowedRequisites"))
, maxSize(symbols.create("maxSize"))
, maxClosureSize(symbols.create("maxClosureSize"))
, builder(symbols.create("builder"))
, args(symbols.create("args"))
, contentAddressed(symbols.create("__contentAddressed"))
, impure(symbols.create("__impure"))
, outputHash(symbols.create("outputHash"))
, outputHashAlgo(symbols.create("outputHashAlgo"))
, outputHashMode(symbols.create("outputHashMode"))
, recurseForDerivations(symbols.create("recurseForDerivations"))
, description(symbols.create("description"))
, self(symbols.create("self"))
, startSet(symbols.create("startSet"))
, operator_(symbols.create("operator"))
, key(symbols.create("key"))
, path(symbols.create("path"))
, prefix(symbols.create("prefix"))
, outputSpecified(symbols.create("outputSpecified"))
, exprSymbols{
.sub = symbols.create("__sub"),
.lessThan = symbols.create("__lessThan"),
.mul = symbols.create("__mul"),
.div = symbols.create("__div"),
.or_ = symbols.create("or"),
.findFile = symbols.create("__findFile"),
.nixPath = symbols.create("__nixPath"),
.body = symbols.create("body"),
.overrides = symbols.create("__overrides"),
}
{
}
EvalMemory::EvalMemory()
{
assert(libexprInitialised);
@@ -413,8 +357,7 @@ Evaluator::Evaluator(
std::shared_ptr<Store> buildStore,
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl
)
: s(symbols)
, paths(aio, store, [&] {
: paths(aio, store, [&] {
SearchPath searchPath;
if (!evalSettings.pureEval) {
for (auto & i : _searchPath.elements)
@@ -962,8 +905,8 @@ void EvalState::mkPos(Value & v, PosIdx p)
auto origin = ctx.positions.originOf(p);
if (auto path = std::get_if<CheckedSourcePath>(&origin)) {
auto attrs = ctx.buildBindings(3);
attrs.alloc(ctx.s.file).mkString(path->to_string());
makePositionThunks(*this, p, attrs.alloc(ctx.s.line), attrs.alloc(ctx.s.column));
attrs.alloc(ctx.symbols.sym_file).mkString(path->to_string());
makePositionThunks(*this, p, attrs.alloc(ctx.symbols.sym_line), attrs.alloc(ctx.symbols.sym_column));
v.mkAttrs(attrs);
} else
v.mkNull();
@@ -1182,7 +1125,7 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
dynamicEnv = &env2;
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr;
ExprAttrs::AttrDefs::iterator overrides = attrs.find(state.ctx.s.overrides);
ExprAttrs::AttrDefs::iterator overrides = attrs.find(state.ctx.symbols.sym___overrides);
bool hasOverrides = overrides != attrs.end();
/* The recursive attributes are evaluated in the new
@@ -1797,7 +1740,8 @@ void EvalState::callFunction(Value & fun, std::span<Value> args, Value & vRes, c
}
}
else if (vCur.type() == nAttrs && (functor = vCur.attrs()->get(ctx.s.functor))) {
else if (vCur.type() == nAttrs && (functor = vCur.attrs()->get(ctx.symbols.sym___functor)))
{
/* 'vCur' may be allocated on the stack of the calling
function, but for functors we may keep a reference, so
heap-allocate a copy and use that instead. */
@@ -1811,14 +1755,17 @@ void EvalState::callFunction(Value & fun, std::span<Value> args, Value & vRes, c
args = args.subspan(1);
}
else
ctx.errors.make<TypeError>(
else {
ctx.errors
.make<TypeError>(
"attempt to call something which is not a function but %1%: %2%",
showType(vCur),
ValuePrinter(*this, vCur, errorPrintOptions))
ValuePrinter(*this, vCur, errorPrintOptions)
)
.atPos(pos)
.debugThrow();
}
}
vRes = vCur;
}
@@ -1856,7 +1803,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res, PosI
forceValue(fun, pos);
if (fun.type() == nAttrs) {
auto found = fun.attrs()->get(ctx.s.functor);
auto found = fun.attrs()->get(ctx.symbols.sym___functor);
if (found) {
Value v;
callFunction(found->value, fun, v, pos);
@@ -2322,7 +2269,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
bool EvalState::isFunctor(Value & fun)
{
return fun.type() == nAttrs && fun.attrs()->get(ctx.s.functor);
return fun.type() == nAttrs && fun.attrs()->get(ctx.symbols.sym___functor);
}
@@ -2397,7 +2344,7 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s
bool EvalState::isDerivation(Value & v)
{
if (v.type() != nAttrs) return false;
auto i = v.attrs()->get(ctx.s.type);
auto i = v.attrs()->get(ctx.symbols.sym_type);
if (!i) {
return false;
}
@@ -2412,7 +2359,7 @@ bool EvalState::isDerivation(Value & v)
std::optional<std::string> EvalState::tryAttrsToString(const PosIdx pos, Value & v,
NixStringContext & context, StringCoercionMode mode, bool copyToStore)
{
auto i = v.attrs()->get(ctx.s.toString);
auto i = v.attrs()->get(ctx.symbols.sym___toString);
if (i) {
Value v1;
try {
@@ -2461,7 +2408,7 @@ BackedStringView EvalState::coerceToString(
auto maybeString = tryAttrsToString(pos, v, context, mode, copyToStore);
if (maybeString)
return std::move(*maybeString);
auto i = v.attrs()->get(ctx.s.outPath);
auto i = v.attrs()->get(ctx.symbols.sym_outPath);
if (!i) {
ctx.errors.make<TypeError>(
"cannot coerce %1% to a string: %2%",
@@ -2701,8 +2648,8 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
/* If both sets denote a derivation (type = "derivation"),
then compare their outPaths. */
if (isDerivation(v1) && isDerivation(v2)) {
auto i = v1.attrs()->get(ctx.s.outPath);
auto j = v2.attrs()->get(ctx.s.outPath);
auto i = v1.attrs()->get(ctx.symbols.sym_outPath);
auto j = v2.attrs()->get(ctx.symbols.sym_outPath);
if (i && j) {
return eqValues(i->value, j->value, pos, errorCtx);
}
+1 -16
View File
@@ -163,20 +163,6 @@ public:
}
};
struct StaticSymbols
{
const Symbol outPath, drvPath, type, meta, name, value, system, overrides, outputs, outputName,
ignoreNulls, file, line, column, functor, toString, right, wrong, structuredAttrs,
allowedReferences, allowedRequisites, disallowedReferences, disallowedRequisites, maxSize,
maxClosureSize, builder, args, contentAddressed, impure, outputHash, outputHashAlgo,
outputHashMode, recurseForDerivations, description, self, startSet, operator_, key,
path, prefix, outputSpecified;
const Expr::AstSymbols exprSymbols;
explicit StaticSymbols(SymbolTable & symbols);
};
class EvalMemory
{
static constexpr size_t CACHES = 8;
@@ -491,9 +477,8 @@ class Evaluator
EvalState * activeEval = nullptr;
public:
SymbolTable symbols;
NixSymbolTable symbols;
PosTable positions;
const StaticSymbols s;
EvalMemory mem;
EvalRuntimeCaches caches;
EvalPaths paths;
+17 -13
View File
@@ -334,7 +334,7 @@ static Flake getFlake(
Value vInfo;
state.eval(flakeExpr, vInfo);
if (auto description = vInfo.attrs()->get(state.ctx.s.description)) {
if (auto description = vInfo.attrs()->get(state.ctx.symbols.sym_description)) {
expectType(state, nString, description->value, description->pos);
flake.description = description->value.str();
}
@@ -367,7 +367,7 @@ static Flake getFlake(
flake.resolvedRef = resolvedRef;
}
if (auto outputs = vInfo.attrs()->get(state.ctx.s.outputs)) {
if (auto outputs = vInfo.attrs()->get(state.ctx.symbols.sym_outputs)) {
expectType(state, nFunction, outputs->value, outputs->pos);
if (outputs->value.isLambda()) {
@@ -376,19 +376,19 @@ static Flake getFlake(
pattern)
{
for (auto & formal : pattern->formals) {
if (formal.name != state.ctx.s.self)
if (formal.name != state.ctx.symbols.sym_self) {
flake.inputs.emplace(
state.ctx.symbols[formal.name],
FlakeInput{
.ref = parseFlakeRef(std::string(state.ctx.symbols[formal.name]))
}
FlakeInput{.ref = parseFlakeRef(std::string(state.ctx.symbols[formal.name]))}
);
}
}
}
}
} else
} else {
throw Error("flake '%s' lacks attribute 'outputs'", lockedRef);
}
auto sNixConfig = state.ctx.symbols.create("nixConfig");
@@ -457,12 +457,16 @@ static Flake getFlake(
}
for (auto & attr : *vInfo.attrs()) {
if (attr.name != state.ctx.s.description &&
attr.name != sInputs &&
attr.name != state.ctx.s.outputs &&
attr.name != sNixConfig)
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
lockedRef, state.ctx.symbols[attr.name], state.ctx.positions[attr.pos]);
if (attr.name != state.ctx.symbols.sym_description && attr.name != sInputs
&& attr.name != state.ctx.symbols.sym_outputs && attr.name != sNixConfig)
{
throw Error(
"flake '%s' has an unsupported attribute '%s', at %s",
lockedRef,
state.ctx.symbols[attr.name],
state.ctx.positions[attr.pos]
);
}
}
return flake;
+11 -11
View File
@@ -64,7 +64,7 @@ try {
std::string DrvInfo::queryName(EvalState & state)
{
if (name == "" && attrs) {
auto i = attrs->get(state.ctx.s.name);
auto i = attrs->get(state.ctx.symbols.sym_name);
if (!i) {
state.ctx.errors.make<TypeError>("derivation name missing").debugThrow();
}
@@ -79,7 +79,7 @@ std::string DrvInfo::queryName(EvalState & state)
std::string DrvInfo::querySystem(EvalState & state)
{
if (system == "" && attrs) {
auto i = attrs->get(state.ctx.s.system);
auto i = attrs->get(state.ctx.symbols.sym_system);
system = !i
? "unknown"
: state.forceStringNoCtx(
@@ -93,7 +93,7 @@ std::string DrvInfo::querySystem(EvalState & state)
std::optional<StorePath> DrvInfo::queryDrvPath(EvalState & state)
{
if (!drvPath && attrs) {
auto i = attrs->get(state.ctx.s.drvPath);
auto i = attrs->get(state.ctx.symbols.sym_drvPath);
NixStringContext context;
if (!i) {
drvPath = {std::nullopt};
@@ -121,7 +121,7 @@ StorePath DrvInfo::requireDrvPath(EvalState & state)
StorePath DrvInfo::queryOutPath(EvalState & state)
{
if (!outPath && attrs) {
auto i = attrs->get(state.ctx.s.outPath);
auto i = attrs->get(state.ctx.symbols.sym_outPath);
NixStringContext context;
if (i) {
outPath = state.coerceToStorePath(
@@ -150,7 +150,7 @@ void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
return;
}
const Attr * outputs = this->attrs->get(state.ctx.s.outputs);
const Attr * outputs = this->attrs->get(state.ctx.symbols.sym_outputs);
if (outputs == nullptr) {
fillDefault();
return;
@@ -183,7 +183,7 @@ void DrvInfo::fillOutputs(EvalState & state, bool withPaths)
state.forceAttrs(out->value, outputs->pos, errMsg);
// ...and evaluate its `outPath` attribute.
const Attr * outPath = out->value.attrs()->get(state.ctx.s.outPath);
const Attr * outPath = out->value.attrs()->get(state.ctx.symbols.sym_outPath);
if (outPath == nullptr) {
continue;
// FIXME: throw error?
@@ -222,7 +222,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state, bool withPaths, bool o
// output by its attribute, e.g. `pkgs.lix.dev`, which (lol?) sets the magic
// attribute `outputSpecified = true`, and changes the `outputName` attr to the
// explicitly selected-into output.
if (const Attr * outSpecAttr = attrs->get(state.ctx.s.outputSpecified)) {
if (const Attr * outSpecAttr = attrs->get(state.ctx.symbols.sym_outputSpecified)) {
bool outputSpecified = state.forceBool(
outSpecAttr->value,
outSpecAttr->pos,
@@ -264,7 +264,7 @@ DrvInfo::Outputs DrvInfo::queryOutputs(EvalState & state, bool withPaths, bool o
std::string DrvInfo::queryOutputName(EvalState & state)
{
if (outputName == "" && attrs) {
auto i = attrs->get(state.ctx.s.outputName);
auto i = attrs->get(state.ctx.symbols.sym_outputName);
outputName = i ? state.forceStringNoCtx(
i->value, noPos, "while evaluating the output name of a derivation"
)
@@ -278,7 +278,7 @@ Bindings * DrvInfo::getMeta(EvalState & state)
{
if (meta) return meta;
if (!attrs) return 0;
auto a = attrs->get(state.ctx.s.meta);
auto a = attrs->get(state.ctx.symbols.sym_meta);
if (!a) {
return 0;
}
@@ -310,7 +310,7 @@ bool DrvInfo::checkMeta(EvalState & state, Value & v)
return true;
}
else if (v.type() == nAttrs) {
auto i = v.attrs()->get(state.ctx.s.outPath);
auto i = v.attrs()->get(state.ctx.symbols.sym_outPath);
if (i) {
return false;
}
@@ -524,7 +524,7 @@ static void getDerivations(EvalState & state, Value & vIn, PosIdx pos,
`recurseForDerivations = true' attribute. */
if (attr->value.type() == nAttrs) {
const Attr * recurseForDrvs =
attr->value.attrs()->get(state.ctx.s.recurseForDerivations);
attr->value.attrs()->get(state.ctx.symbols.sym_recurseForDerivations);
if (recurseForDrvs == nullptr) {
continue;
}
-3
View File
@@ -114,9 +114,6 @@ protected:
Expr(const PosIdx pos) : pos(pos) {};
public:
struct AstSymbols {
Symbol sub, lessThan, mul, div, or_, findFile, nixPath, body, overrides;
};
PosIdx pos;
+14 -10
View File
@@ -137,7 +137,7 @@ struct ExprState
std::unique_ptr<Expr> order(PosIdx pos, bool less, State & state)
{
return call(pos, state, state.s.lessThan, !less);
return call(pos, state, state.symbols.sym___lessThan, !less);
}
std::unique_ptr<Expr> concatStrings(PosIdx pos)
@@ -153,7 +153,9 @@ struct ExprState
std::vector<std::unique_ptr<Expr>> args(2);
args[0] = std::make_unique<ExprInt>(pos, 0);
args[1] = popExprOnly();
return std::make_unique<ExprCall>(pos, state.mkInternalVar(pos, state.s.sub), std::move(args));
return std::make_unique<ExprCall>(
pos, state.mkInternalVar(pos, state.symbols.sym___sub), std::move(args)
);
}
void applyOp(PosIdx pos, auto & op, State & state) {
@@ -176,9 +178,9 @@ struct ExprState
[&](Op::update) { return applyBinary<ExprOpUpdate>(pos); },
[&](Op::not_) { return applyUnary<ExprOpNot>(pos); },
[&](Op::plus) { return concatStrings(pos); },
[&] (Op::minus) { return call(pos, state, state.s.sub); },
[&] (Op::mul) { return call(pos, state, state.s.mul); },
[&] (Op::div) { return call(pos, state, state.s.div); },
[&](Op::minus) { return call(pos, state, state.symbols.sym___sub); },
[&](Op::mul) { return call(pos, state, state.symbols.sym___mul); },
[&](Op::div) { return call(pos, state, state.symbols.sym___div); },
[&](Op::concat) { return applyBinary<ExprOpConcatLists>(pos); },
[&](has_attr & a) { return applyUnary<ExprOpHasAttr>(pos, std::move(a.path)); },
[&](Op::unary_minus) { return negate(pos, state); },
@@ -755,7 +757,7 @@ template<> struct BuildAST<grammar::v1::path::searched_path> {
* https://github.com/NixOS/nix/commit/62a6eeb1f3da0a5954ad2da54c454eb7fc1c6e5d
* (TODO: Provide a better and officially supported and documented mechanism for doing this)
*/
args[0] = std::make_unique<ExprVar>(pos, ps.s.nixPath);
args[0] = std::make_unique<ExprVar>(pos, ps.symbols.sym___nixPath);
args[1] = std::make_unique<ExprString>(pos, in.string());
s.parts.emplace_back(
pos,
@@ -765,8 +767,10 @@ template<> struct BuildAST<grammar::v1::path::searched_path> {
* until we can figure out how to design a better replacement.
* https://git.lix.systems/lix-project/lix/issues/599
*/
std::make_unique<ExprVar>(pos, ps.s.findFile),
std::move(args)));
std::make_unique<ExprVar>(pos, ps.symbols.sym___findFile),
std::move(args)
)
);
}
};
@@ -831,7 +835,7 @@ template<> struct BuildAST<grammar::v1::expr::ancient_let> : change_head<Binding
auto pos = ps.at(in);
b.set.pos = pos;
s.emplaceExpr<ExprSelect>(pos, std::make_unique<ExprSet>(std::move(b.set)), pos, ps.s.body);
s.emplaceExpr<ExprSelect>(pos, std::make_unique<ExprSet>(std::move(b.set)), pos, ps.symbols.sym_body);
}
};
@@ -893,7 +897,7 @@ template<> struct BuildAST<grammar::v1::expr::select::attr_or> {
template<> struct BuildAST<grammar::v1::expr::select::as_app_or> {
static void apply(const auto & in, SelectState & s, State & ps) {
std::vector<std::unique_ptr<Expr>> args(1);
args[0] = std::make_unique<ExprVar>(ps.at(in), ps.s.or_);
args[0] = std::make_unique<ExprVar>(ps.at(in), ps.symbols.sym_or);
s->emplaceExpr<ExprCall>(s.pos, s->popExprOnly(), std::move(args));
}
};
-2
View File
@@ -28,7 +28,6 @@ Expr * Evaluator::parse(
positions,
basePath,
positions.addOrigin(origin, length),
this->s.exprSymbols,
featureSettings,
};
@@ -63,7 +62,6 @@ Evaluator::parse_repl(
positions,
basePath,
positions.addOrigin(origin, length),
this->s.exprSymbols,
featureSettings,
};
+2 -3
View File
@@ -25,11 +25,10 @@ struct IndStringLine {
struct State
{
SymbolTable & symbols;
NixSymbolTable & symbols;
PosTable & positions;
SourcePath basePath;
PosTable::Origin origin;
const Expr::AstSymbols & s;
const FeatureSettings & featureSettings;
bool hasWarnedAboutBadLineEndings = false; // State to only warn on first occurrence
@@ -194,7 +193,7 @@ inline void State::addAttr(ExprAttrs * attrs, AttrPath && attrPath, std::unique_
// Before inserting new attrs, check for __override and throw an error
// (the error will initially be a warning to ease migration)
if (!featureSettings.isEnabled(Dep::RecSetOverrides) && attr.symbol == s.overrides) {
if (!featureSettings.isEnabled(Dep::RecSetOverrides) && attr.symbol == symbols.sym___overrides) {
if (auto set = dynamic_cast<ExprSet *>(attrs); set && set->recursive) {
overridesFound(pos);
}
+68 -47
View File
@@ -180,11 +180,15 @@ 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.s.drvPath).mkString(path2, {
attrs.alloc(state.ctx.symbols.sym_drvPath)
.mkString(
path2,
{
NixStringContextElem::DrvDeep{.drvPath = *storePath},
});
attrs.alloc(state.ctx.s.name).mkString(drv.env["name"]);
auto & outputsVal = attrs.alloc(state.ctx.s.outputs);
}
);
attrs.alloc(state.ctx.symbols.sym_name).mkString(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};
@@ -544,7 +548,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
/* Get the start set. */
auto startSet = getAttr(
state,
state.ctx.s.startSet,
state.ctx.symbols.sym_startSet,
args[0]->attrs(),
"in the attrset passed as argument to builtins.genericClosure"
);
@@ -568,7 +572,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
/* Get the operator. */
auto op = getAttr(
state,
state.ctx.s.operator_,
state.ctx.symbols.sym_operator,
args[0]->attrs(),
"in the attrset passed as argument to builtins.genericClosure"
);
@@ -599,7 +603,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
auto key = getAttr(
state,
state.ctx.s.key,
state.ctx.symbols.sym_key,
e.attrs(),
"in one of the attrsets generated by (or initially passed to) builtins.genericClosure"
);
@@ -722,9 +726,9 @@ static void prim_tryEval(EvalState & state, Value * * args, Value & v)
return true;
}();
if (success)
attrs.insert(state.ctx.s.value, *args[0]);
attrs.insert(state.ctx.symbols.sym_value, *args[0]);
else
attrs.alloc(state.ctx.s.value).mkBool(false);
attrs.alloc(state.ctx.symbols.sym_value).mkBool(false);
attrs.alloc("success").mkBool(success);
v.mkAttrs(attrs);
@@ -835,7 +839,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
/* Figure out the name first (for stack backtraces). */
auto nameAttr = getAttr(
state,
state.ctx.s.name,
state.ctx.symbols.sym_name,
attrs,
"in the attrset passed as argument to builtins.derivationStrict"
);
@@ -890,7 +894,7 @@ drvName, Bindings * attrs, Value & v)
{
/* Check whether attributes should be passed as a JSON file. */
std::optional<JSON> jsonObject;
auto attr = attrs->get(state.ctx.s.structuredAttrs);
auto attr = attrs->get(state.ctx.symbols.sym___structuredAttrs);
if (attr
&& state.forceBool(
attr->value,
@@ -904,7 +908,7 @@ drvName, Bindings * attrs, Value & v)
/* Check whether null attributes should be ignored. */
bool ignoreNulls = false;
attr = attrs->get(state.ctx.s.ignoreNulls);
attr = attrs->get(state.ctx.symbols.sym___ignoreNulls);
if (attr) {
ignoreNulls = state.forceBool(
attr->value,
@@ -928,7 +932,9 @@ drvName, Bindings * attrs, Value & v)
outputs.insert("out");
for (auto & i : attrs->lexicographicOrder(state.ctx.symbols)) {
if (i->name == state.ctx.s.ignoreNulls) continue;
if (i->name == state.ctx.symbols.sym___ignoreNulls) {
continue;
}
auto & key = state.ctx.symbols[i->name];
vomit("processing attribute '%1%'", key);
@@ -974,14 +980,14 @@ drvName, Bindings * attrs, Value & v)
}
}
if (i->name == state.ctx.s.contentAddressed
if (i->name == state.ctx.symbols.sym___contentAddressed
&& state.forceBool(i->value, noPos, context_below))
{
state.ctx.errors.make<EvalError>("ca derivations are not supported in Lix")
.debugThrow();
}
else if (i->name == state.ctx.s.impure
else if (i->name == state.ctx.symbols.sym___impure
&& state.forceBool(i->value, noPos, context_below))
{
state.ctx.errors.make<EvalError>("impure derivations are not supported in Lix")
@@ -990,7 +996,7 @@ drvName, Bindings * attrs, Value & v)
/* The `args' attribute is special: it supplies the
command-line arguments to the builder. */
else if (i->name == state.ctx.s.args)
else if (i->name == state.ctx.symbols.sym_args)
{
state.forceList(i->value, noPos, context_below);
for (auto & elem : i->value.listItems()) {
@@ -1009,27 +1015,28 @@ drvName, Bindings * attrs, Value & v)
/* All other attributes are passed to the builder through
the environment. */
else
{
else {
if (jsonObject) {
if (i->name == state.ctx.s.structuredAttrs) continue;
if (i->name == state.ctx.symbols.sym___structuredAttrs) {
continue;
}
(*jsonObject)[std::string(key)] =
printValueAsJSON(state, true, i->value, noPos, context);
if (i->name == state.ctx.s.builder)
if (i->name == state.ctx.symbols.sym_builder) {
drv.builder = state.forceString(i->value, context, noPos, context_below);
else if (i->name == state.ctx.s.system)
} else if (i->name == state.ctx.symbols.sym_system) {
drv.platform = state.forceStringNoCtx(i->value, noPos, context_below);
else if (i->name == state.ctx.s.outputHash)
} else if (i->name == state.ctx.symbols.sym_outputHash) {
outputHash = state.forceStringNoCtx(i->value, noPos, context_below);
else if (i->name == state.ctx.s.outputHashAlgo)
} else if (i->name == state.ctx.symbols.sym_outputHashAlgo) {
outputHashAlgo = state.forceStringNoCtx(i->value, noPos, context_below);
else if (i->name == state.ctx.s.outputHashMode)
} else if (i->name == state.ctx.symbols.sym_outputHashMode) {
handleHashMode(state.forceStringNoCtx(i->value, noPos, context_below));
else if (i->name == state.ctx.s.outputs) {
} else if (i->name == state.ctx.symbols.sym_outputs) {
/* Require outputs to be a list of strings. */
state.forceList(i->value, noPos, context_below);
Strings ss;
@@ -1039,48 +1046,54 @@ drvName, Bindings * attrs, Value & v)
handleOutputs(ss);
}
if (i->name == state.ctx.s.allowedReferences)
if (i->name == state.ctx.symbols.sym_allowedReferences) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'allowedReferences'; use "
"'outputChecks.<output>.allowedReferences' instead",
drvName
);
if (i->name == state.ctx.s.allowedRequisites)
}
if (i->name == state.ctx.symbols.sym_allowedRequisites) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'allowedRequisites'; use "
"'outputChecks.<output>.allowedRequisites' instead",
drvName
);
if (i->name == state.ctx.s.disallowedReferences)
}
if (i->name == state.ctx.symbols.sym_disallowedReferences) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'disallowedReferences'; use "
"'outputChecks.<output>.disallowedReferences' instead",
drvName
);
if (i->name == state.ctx.s.disallowedRequisites)
}
if (i->name == state.ctx.symbols.sym_disallowedRequisites) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'disallowedRequisites'; use "
"'outputChecks.<output>.disallowedRequisites' instead",
drvName
);
if (i->name == state.ctx.s.maxSize)
}
if (i->name == state.ctx.symbols.sym_maxSize) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'maxSize'; use "
"'outputChecks.<output>.maxSize' instead",
drvName
);
if (i->name == state.ctx.s.maxClosureSize)
}
if (i->name == state.ctx.symbols.sym_maxClosureSize) {
printTaggedWarning(
"In a derivation named '%s', 'structuredAttrs' disables the effect of "
"the derivation attribute 'maxClosureSize'; use "
"'outputChecks.<output>.maxClosureSize' instead",
drvName
);
}
} else {
auto s = state
@@ -1093,17 +1106,21 @@ drvName, Bindings * attrs, Value & v)
)
.toOwned();
drv.env.emplace(key, s);
if (i->name == state.ctx.s.builder) {
if (i->name == state.ctx.symbols.sym_builder) {
drv.builder = std::move(s);
} else if (i->name == state.ctx.s.system)
} else if (i->name == state.ctx.symbols.sym_system) {
drv.platform = std::move(s);
else if (i->name == state.ctx.s.outputHash) outputHash = std::move(s);
else if (i->name == state.ctx.s.outputHashAlgo) outputHashAlgo = std::move(s);
else if (i->name == state.ctx.s.outputHashMode) handleHashMode(s);
else if (i->name == state.ctx.s.outputs)
} else if (i->name == state.ctx.symbols.sym_outputHash) {
outputHash = std::move(s);
} else if (i->name == state.ctx.symbols.sym_outputHashAlgo) {
outputHashAlgo = std::move(s);
} else if (i->name == state.ctx.symbols.sym_outputHashMode) {
handleHashMode(s);
} else if (i->name == state.ctx.symbols.sym_outputs) {
handleOutputs(tokenizeString<Strings>(s));
}
}
}
} catch (Error & e) {
e.pushTrace(Trace::fromDrvAttr(
@@ -1239,9 +1256,13 @@ drvName, Bindings * attrs, Value & v)
}
auto result = state.ctx.buildBindings(1 + drv.outputs.size());
result.alloc(state.ctx.s.drvPath).mkString(drvPathS, {
result.alloc(state.ctx.symbols.sym_drvPath)
.mkString(
drvPathS,
{
NixStringContextElem::DrvDeep{.drvPath = drvPath},
});
}
);
for (auto & i : drv.outputs)
mkOutputString(state, result, drvPath, i);
@@ -1414,7 +1435,7 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
);
std::string prefix;
auto i = v2.attrs()->get(state.ctx.s.prefix);
auto i = v2.attrs()->get(state.ctx.symbols.sym_prefix);
if (i) {
prefix = state.forceStringNoCtx(
i->value,
@@ -1424,7 +1445,7 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
);
}
i = getAttr(state, state.ctx.s.path, v2.attrs(), "in an element of the __nixPath");
i = getAttr(state, state.ctx.symbols.sym_path, v2.attrs(), "in an element of the __nixPath");
NixStringContext context;
auto path = state
@@ -1728,7 +1749,7 @@ static void prim_path(EvalState & state, Value * * args, Value & v)
context,
"while evaluating the 'path' attribute passed to 'builtins.path'"
));
} else if (attr.name == state.ctx.s.name) {
} else if (attr.name == state.ctx.symbols.sym_name) {
name = state.forceStringNoCtx(
attr.value,
attr.pos,
@@ -1962,7 +1983,7 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
v2, noPos, "while evaluating an element of the list passed to builtins.listToAttrs"
);
auto j = getAttr(state, state.ctx.s.name, v2.attrs(), "in a {name=...; value=...;} pair");
auto j = getAttr(state, state.ctx.symbols.sym_name, v2.attrs(), "in a {name=...; value=...;} pair");
auto name = state.forceStringNoCtx(
j->value,
@@ -1974,7 +1995,7 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
auto sym = state.ctx.symbols.create(name);
if (seen.insert(sym).second) {
auto j2 =
getAttr(state, state.ctx.s.value, v2.attrs(), "in a {name=...; value=...;} pair");
getAttr(state, state.ctx.symbols.sym_value, v2.attrs(), "in a {name=...; value=...;} pair");
attrs.insert(sym, j2->value, j2->pos);
}
}
@@ -2466,7 +2487,7 @@ static void prim_partition(EvalState & state, Value * * args, Value & v)
auto attrs = state.ctx.buildBindings(2);
auto & vRight = attrs.alloc(state.ctx.s.right);
auto & vRight = attrs.alloc(state.ctx.symbols.sym_right);
auto rsize = right.size();
auto rlist = state.ctx.mem.newList(rsize);
vRight = {NewValueAs::list, rlist};
@@ -2474,7 +2495,7 @@ static void prim_partition(EvalState & state, Value * * args, Value & v)
rlist->elems[i] = elems[idx];
}
auto & vWrong = attrs.alloc(state.ctx.s.wrong);
auto & vWrong = attrs.alloc(state.ctx.symbols.sym_wrong);
auto wsize = wrong.size();
auto wlist = state.ctx.mem.newList(wsize);
vWrong = {NewValueAs::list, wlist};
@@ -2982,7 +3003,7 @@ 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.s.name).mkString(parsed.name);
attrs.alloc(state.ctx.symbols.sym_name).mkString(parsed.name);
attrs.alloc("version").mkString(parsed.version);
v.mkAttrs(attrs);
}
+4 -4
View File
@@ -136,11 +136,11 @@ void prim_getContext(EvalState & state, Value * * args, Value & v)
for (const auto & info : contextInfos) {
auto infoAttrs = state.ctx.buildBindings(3);
if (info.second.path)
infoAttrs.alloc(state.ctx.s.path).mkBool(true);
infoAttrs.alloc(state.ctx.symbols.sym_path).mkBool(true);
if (info.second.allOutputs)
infoAttrs.alloc(sAllOutputs).mkBool(true);
if (!info.second.outputs.empty()) {
auto & outputsVal = infoAttrs.alloc(state.ctx.s.outputs);
auto & outputsVal = infoAttrs.alloc(state.ctx.symbols.sym_outputs);
auto content = state.ctx.mem.newList(info.second.outputs.size());
outputsVal = {NewValueAs::list, content};
for (const auto & [i, output] : enumerate(info.second.outputs))
@@ -177,7 +177,7 @@ void prim_appendContext(EvalState & state, Value ** args, Value & v)
if (!settings.readOnlyMode)
state.aio.blockOn(state.ctx.store->ensurePath(namePath));
state.forceAttrs(i.value, i.pos, "while evaluating the value of a string context");
auto a = i.value.attrs()->get(state.ctx.s.path);
auto a = i.value.attrs()->get(state.ctx.symbols.sym_path);
if (a) {
if (state.forceBool(
a->value, a->pos, "while evaluating the `path` attribute of a string context"
@@ -209,7 +209,7 @@ void prim_appendContext(EvalState & state, Value ** args, Value & v)
}
}
a = i.value.attrs()->get(state.ctx.s.outputs);
a = i.value.attrs()->get(state.ctx.symbols.sym_outputs);
if (a) {
state.forceList(
a->value, a->pos, "while evaluating the `outputs` attribute of a string context"
+1 -1
View File
@@ -88,7 +88,7 @@ void prim_fetchMercurial(EvalState & state, Value ** args, Value & v)
auto [tree, input2] = state.aio.blockOn(input.fetch(state.ctx.store));
auto attrs2 = state.ctx.buildBindings(8);
state.ctx.paths.mkStorePathString(tree.storePath, attrs2.alloc(state.ctx.s.outPath));
state.ctx.paths.mkStorePathString(tree.storePath, attrs2.alloc(state.ctx.symbols.sym_outPath));
if (input2.getRef())
attrs2.alloc("branch").mkString(*input2.getRef());
// Backward compatibility: set 'rev' to
+5 -4
View File
@@ -26,8 +26,7 @@ void emitTreeAttrs(
auto attrs = state.buildBindings(10);
state.paths.mkStorePathString(tree.storePath, attrs.alloc(state.s.outPath));
state.paths.mkStorePathString(tree.storePath, attrs.alloc(state.symbols.sym_outPath));
// FIXME: support arbitrary input attributes.
@@ -122,7 +121,7 @@ static void fetchTree(
fetchers::Attrs attrs;
if (auto aType = args[0]->attrs()->get(state.ctx.s.type)) {
if (auto aType = args[0]->attrs()->get(state.ctx.symbols.sym_type)) {
if (type)
state.ctx.errors.make<EvalError>(
"unexpected attribute 'type'"
@@ -141,7 +140,9 @@ static void fetchTree(
attrs.emplace("type", type.value());
for (auto & attr : *args[0]->attrs()) {
if (attr.name == state.ctx.s.type) continue;
if (attr.name == state.ctx.symbols.sym_type) {
continue;
}
state.forceValue(attr.value, attr.pos);
if (attr.value.type() == nPath || attr.value.type() == nString) {
auto s =
+1 -1
View File
@@ -232,7 +232,7 @@ private:
void printDerivation(Value & v)
{
auto i = v.attrs()->get(state.ctx.s.drvPath);
auto i = v.attrs()->get(state.ctx.symbols.sym_drvPath);
NixStringContext context;
std::string storePath;
if (i) {
+1 -1
View File
@@ -51,7 +51,7 @@ JSON printValueAsJSON(EvalState & state, bool strict,
out = *maybeString;
break;
}
auto i = v.attrs()->get(state.ctx.s.outPath);
auto i = v.attrs()->get(state.ctx.symbols.sym_outPath);
if (!i) {
out = JSON::object();
StringSet names;
+2 -2
View File
@@ -87,7 +87,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
auto a = v.attrs()->get(state.ctx.symbols.create("derivation"));
Path drvPath;
a = v.attrs()->get(state.ctx.s.drvPath);
a = v.attrs()->get(state.ctx.symbols.sym_drvPath);
if (a) {
if (strict) {
state.forceValue(a->value, a->pos);
@@ -97,7 +97,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
}
}
a = v.attrs()->get(state.ctx.s.outPath);
a = v.attrs()->get(state.ctx.symbols.sym_outPath);
if (a) {
if (strict) {
state.forceValue(a->value, a->pos);
+3 -3
View File
@@ -104,14 +104,14 @@ struct CmdBundle : InstallableCommand
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
}
auto attr1 = vRes.attrs()->get(evaluator->s.drvPath);
auto attr1 = vRes.attrs()->get(evaluator->symbols.sym_drvPath);
if (!attr1)
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
NixStringContext context2;
auto drvPath = evalState->coerceToStorePath(attr1->pos, attr1->value, context2, "");
auto attr2 = vRes.attrs()->get(evaluator->s.outPath);
auto attr2 = vRes.attrs()->get(evaluator->symbols.sym_outPath);
if (!attr2)
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
@@ -125,7 +125,7 @@ struct CmdBundle : InstallableCommand
}));
if (!outLink) {
auto * attr = vRes.attrs()->get(evaluator->s.name);
auto * attr = vRes.attrs()->get(evaluator->symbols.sym_name);
if (!attr)
throw Error("attribute 'name' missing");
outLink = evalState->forceStringNoCtx(attr->value, attr->pos, "");
+1 -1
View File
@@ -230,7 +230,7 @@ try {
if (name == "recurseForDerivations" &&
!args.forceRecurse) {
auto attrv = v.attrs()->get(
evaluator->s.recurseForDerivations);
evaluator->symbols.sym_recurseForDerivations);
recurse = state->forceBool(
attrv->value, attrv->pos,
"while evaluating recurseForDerivations");
+1 -1
View File
@@ -440,7 +440,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation)
vDerivation.mkString("derivation");
BindingsBuilder builder = evaluator.buildBindings(10);
builder.insert(evaluator.s.type, vDerivation);
builder.insert(evaluator.symbols.sym_type, vDerivation);
Value vAttrs;
vAttrs.mkAttrs(builder.finish());