mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 20:16:03 +01:00
Merge pull request #13879 from xokdvium/static-alloc-symbol-ids
libexpr: Statically allocate commonly used symbols
This commit is contained in:
commit
1f7d43e5bd
23 changed files with 313 additions and 255 deletions
|
|
@ -105,8 +105,8 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
|
||||||
|
|
||||||
std::optional<NixInt::Inner> priority;
|
std::optional<NixInt::Inner> priority;
|
||||||
|
|
||||||
if (attr->maybeGetAttr(state->sOutputSpecified)) {
|
if (attr->maybeGetAttr(state->s.outputSpecified)) {
|
||||||
} else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
} else if (auto aMeta = attr->maybeGetAttr(state->s.meta)) {
|
||||||
if (auto aPriority = aMeta->maybeGetAttr("priority"))
|
if (auto aPriority = aMeta->maybeGetAttr("priority"))
|
||||||
priority = aPriority->getInt().value;
|
priority = aPriority->getInt().value;
|
||||||
}
|
}
|
||||||
|
|
@ -119,12 +119,12 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths()
|
||||||
overloaded{
|
overloaded{
|
||||||
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
[&](const ExtendedOutputsSpec::Default & d) -> OutputsSpec {
|
||||||
StringSet outputsToInstall;
|
StringSet outputsToInstall;
|
||||||
if (auto aOutputSpecified = attr->maybeGetAttr(state->sOutputSpecified)) {
|
if (auto aOutputSpecified = attr->maybeGetAttr(state->s.outputSpecified)) {
|
||||||
if (aOutputSpecified->getBool()) {
|
if (aOutputSpecified->getBool()) {
|
||||||
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
if (auto aOutputName = attr->maybeGetAttr("outputName"))
|
||||||
outputsToInstall = {aOutputName->getString()};
|
outputsToInstall = {aOutputName->getString()};
|
||||||
}
|
}
|
||||||
} else if (auto aMeta = attr->maybeGetAttr(state->sMeta)) {
|
} else if (auto aMeta = attr->maybeGetAttr(state->s.meta)) {
|
||||||
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
if (auto aOutputsToInstall = aMeta->maybeGetAttr("outputsToInstall"))
|
||||||
for (auto & s : aOutputsToInstall->getListOfStrings())
|
for (auto & s : aOutputsToInstall->getListOfStrings())
|
||||||
outputsToInstall.insert(s);
|
outputsToInstall.insert(s);
|
||||||
|
|
|
||||||
|
|
@ -393,7 +393,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation)
|
||||||
vDerivation.mkString("derivation");
|
vDerivation.mkString("derivation");
|
||||||
|
|
||||||
BindingsBuilder builder(state, state.allocBindings(10));
|
BindingsBuilder builder(state, state.allocBindings(10));
|
||||||
builder.insert(state.sType, &vDerivation);
|
builder.insert(state.s.type, &vDerivation);
|
||||||
|
|
||||||
Value vAttrs;
|
Value vAttrs;
|
||||||
vAttrs.mkAttrs(builder.finish());
|
vAttrs.mkAttrs(builder.finish());
|
||||||
|
|
@ -438,8 +438,8 @@ TEST_F(ValuePrintingTests, ansiColorsDerivationError)
|
||||||
vDerivation.mkString("derivation");
|
vDerivation.mkString("derivation");
|
||||||
|
|
||||||
BindingsBuilder builder(state, state.allocBindings(10));
|
BindingsBuilder builder(state, state.allocBindings(10));
|
||||||
builder.insert(state.sType, &vDerivation);
|
builder.insert(state.s.type, &vDerivation);
|
||||||
builder.insert(state.sDrvPath, &vError);
|
builder.insert(state.s.drvPath, &vError);
|
||||||
|
|
||||||
Value vAttrs;
|
Value vAttrs;
|
||||||
vAttrs.mkAttrs(builder.finish());
|
vAttrs.mkAttrs(builder.finish());
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ AttrCursor::AttrCursor(
|
||||||
AttrKey AttrCursor::getKey()
|
AttrKey AttrCursor::getKey()
|
||||||
{
|
{
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return {0, root->state.sEpsilon};
|
return {0, root->state.s.epsilon};
|
||||||
if (!parent->first->cachedValue) {
|
if (!parent->first->cachedValue) {
|
||||||
parent->first->cachedValue = root->db->getAttr(parent->first->getKey());
|
parent->first->cachedValue = root->db->getAttr(parent->first->getKey());
|
||||||
assert(parent->first->cachedValue);
|
assert(parent->first->cachedValue);
|
||||||
|
|
@ -702,7 +702,7 @@ bool AttrCursor::isDerivation()
|
||||||
|
|
||||||
StorePath AttrCursor::forceDerivation()
|
StorePath AttrCursor::forceDerivation()
|
||||||
{
|
{
|
||||||
auto aDrvPath = getAttr(root->state.sDrvPath);
|
auto aDrvPath = getAttr(root->state.s.drvPath);
|
||||||
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
|
||||||
drvPath.requireDerivation();
|
drvPath.requireDerivation();
|
||||||
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ FrameInfo SampleStack::getPrimOpFrameInfo(const PrimOp & primOp, std::span<Value
|
||||||
/* Error context strings don't actually matter, since we ignore all eval errors. */
|
/* Error context strings don't actually matter, since we ignore all eval errors. */
|
||||||
state.forceAttrs(*args[0], pos, "");
|
state.forceAttrs(*args[0], pos, "");
|
||||||
auto attrs = args[0]->attrs();
|
auto attrs = args[0]->attrs();
|
||||||
auto nameAttr = state.getAttr(state.sName, attrs, "");
|
auto nameAttr = state.getAttr(state.s.name, attrs, "");
|
||||||
auto drvName = std::string(state.forceStringNoCtx(*nameAttr->value, pos, ""));
|
auto drvName = std::string(state.forceStringNoCtx(*nameAttr->value, pos, ""));
|
||||||
return DerivationStrictFrameInfo{.callPos = pos, .drvName = std::move(drvName)};
|
return DerivationStrictFrameInfo{.callPos = pos, .drvName = std::move(drvName)};
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
@ -211,7 +211,7 @@ FrameInfo SampleStack::getFrameInfoFromValueAndPos(const Value & v, std::span<Va
|
||||||
/* Resolve primOp eagerly. Must not hold on to a reference to a Value. */
|
/* Resolve primOp eagerly. Must not hold on to a reference to a Value. */
|
||||||
return PrimOpFrameInfo{.expr = v.primOpAppPrimOp(), .callPos = pos};
|
return PrimOpFrameInfo{.expr = v.primOpAppPrimOp(), .callPos = pos};
|
||||||
else if (state.isFunctor(v)) {
|
else if (state.isFunctor(v)) {
|
||||||
const auto functor = v.attrs()->get(state.sFunctor);
|
const auto functor = v.attrs()->get(state.s.functor);
|
||||||
if (auto pos_ = posCache.lookup(pos); std::holds_alternative<std::monostate>(pos_.origin))
|
if (auto pos_ = posCache.lookup(pos); std::holds_alternative<std::monostate>(pos_.origin))
|
||||||
/* HACK: In case callsite position is unresolved. */
|
/* HACK: In case callsite position is unresolved. */
|
||||||
return FunctorFrameInfo{.pos = functor->pos};
|
return FunctorFrameInfo{.pos = functor->pos};
|
||||||
|
|
|
||||||
|
|
@ -203,65 +203,10 @@ EvalState::EvalState(
|
||||||
std::shared_ptr<Store> buildStore)
|
std::shared_ptr<Store> buildStore)
|
||||||
: fetchSettings{fetchSettings}
|
: fetchSettings{fetchSettings}
|
||||||
, settings{settings}
|
, settings{settings}
|
||||||
, sWith(symbols.create("<with>"))
|
, symbols(StaticEvalSymbols::staticSymbolTable())
|
||||||
, sOutPath(symbols.create("outPath"))
|
|
||||||
, sDrvPath(symbols.create("drvPath"))
|
|
||||||
, sType(symbols.create("type"))
|
|
||||||
, sMeta(symbols.create("meta"))
|
|
||||||
, sName(symbols.create("name"))
|
|
||||||
, sValue(symbols.create("value"))
|
|
||||||
, sSystem(symbols.create("system"))
|
|
||||||
, sOverrides(symbols.create("__overrides"))
|
|
||||||
, sOutputs(symbols.create("outputs"))
|
|
||||||
, sOutputName(symbols.create("outputName"))
|
|
||||||
, sIgnoreNulls(symbols.create("__ignoreNulls"))
|
|
||||||
, sFile(symbols.create("file"))
|
|
||||||
, sLine(symbols.create("line"))
|
|
||||||
, sColumn(symbols.create("column"))
|
|
||||||
, sFunctor(symbols.create("__functor"))
|
|
||||||
, sToString(symbols.create("__toString"))
|
|
||||||
, sRight(symbols.create("right"))
|
|
||||||
, sWrong(symbols.create("wrong"))
|
|
||||||
, sStructuredAttrs(symbols.create("__structuredAttrs"))
|
|
||||||
, sJson(symbols.create("__json"))
|
|
||||||
, sAllowedReferences(symbols.create("allowedReferences"))
|
|
||||||
, sAllowedRequisites(symbols.create("allowedRequisites"))
|
|
||||||
, sDisallowedReferences(symbols.create("disallowedReferences"))
|
|
||||||
, sDisallowedRequisites(symbols.create("disallowedRequisites"))
|
|
||||||
, sMaxSize(symbols.create("maxSize"))
|
|
||||||
, sMaxClosureSize(symbols.create("maxClosureSize"))
|
|
||||||
, sBuilder(symbols.create("builder"))
|
|
||||||
, sArgs(symbols.create("args"))
|
|
||||||
, sContentAddressed(symbols.create("__contentAddressed"))
|
|
||||||
, sImpure(symbols.create("__impure"))
|
|
||||||
, sOutputHash(symbols.create("outputHash"))
|
|
||||||
, sOutputHashAlgo(symbols.create("outputHashAlgo"))
|
|
||||||
, sOutputHashMode(symbols.create("outputHashMode"))
|
|
||||||
, sRecurseForDerivations(symbols.create("recurseForDerivations"))
|
|
||||||
, sDescription(symbols.create("description"))
|
|
||||||
, sSelf(symbols.create("self"))
|
|
||||||
, sEpsilon(symbols.create(""))
|
|
||||||
, sStartSet(symbols.create("startSet"))
|
|
||||||
, sOperator(symbols.create("operator"))
|
|
||||||
, sKey(symbols.create("key"))
|
|
||||||
, sPath(symbols.create("path"))
|
|
||||||
, sPrefix(symbols.create("prefix"))
|
|
||||||
, sOutputSpecified(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"),
|
|
||||||
}
|
|
||||||
, repair(NoRepair)
|
, repair(NoRepair)
|
||||||
, emptyBindings(0)
|
, emptyBindings(0)
|
||||||
, storeFS(
|
, storeFS(makeMountedSourceAccessor({
|
||||||
makeMountedSourceAccessor(
|
|
||||||
{
|
|
||||||
{CanonPath::root, makeEmptySourceAccessor()},
|
{CanonPath::root, makeEmptySourceAccessor()},
|
||||||
/* In the pure eval case, we can simply require
|
/* In the pure eval case, we can simply require
|
||||||
valid paths. However, in the *impure* eval
|
valid paths. However, in the *impure* eval
|
||||||
|
|
@ -283,8 +228,7 @@ EvalState::EvalState(
|
||||||
*/
|
*/
|
||||||
{CanonPath(store->storeDir), store->getFSAccessor(settings.pureEval)},
|
{CanonPath(store->storeDir), store->getFSAccessor(settings.pureEval)},
|
||||||
}))
|
}))
|
||||||
, rootFS(
|
, rootFS(({
|
||||||
({
|
|
||||||
/* In pure eval mode, we provide a filesystem that only
|
/* In pure eval mode, we provide a filesystem that only
|
||||||
contains the Nix store.
|
contains the Nix store.
|
||||||
|
|
||||||
|
|
@ -298,17 +242,14 @@ EvalState::EvalState(
|
||||||
|
|
||||||
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
|
auto realStoreDir = dirOf(store->toRealPath(StorePath::dummy));
|
||||||
if (settings.pureEval || store->storeDir != realStoreDir) {
|
if (settings.pureEval || store->storeDir != realStoreDir) {
|
||||||
accessor = settings.pureEval
|
accessor = settings.pureEval ? storeFS : makeUnionSourceAccessor({accessor, storeFS});
|
||||||
? storeFS
|
|
||||||
: makeUnionSourceAccessor({accessor, storeFS});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Apply access control if needed. */
|
/* Apply access control if needed. */
|
||||||
if (settings.restrictEval || settings.pureEval)
|
if (settings.restrictEval || settings.pureEval)
|
||||||
accessor = AllowListSourceAccessor::create(accessor, {}, {},
|
accessor = AllowListSourceAccessor::create(
|
||||||
[&settings](const CanonPath & path) -> RestrictedPathError {
|
accessor, {}, {}, [&settings](const CanonPath & path) -> RestrictedPathError {
|
||||||
auto modeInformation = settings.pureEval
|
auto modeInformation = settings.pureEval ? "in pure evaluation mode (use '--impure' to override)"
|
||||||
? "in pure evaluation mode (use '--impure' to override)"
|
|
||||||
: "in restricted mode";
|
: "in restricted mode";
|
||||||
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
|
throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation);
|
||||||
});
|
});
|
||||||
|
|
@ -654,7 +595,7 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
|
||||||
}
|
}
|
||||||
if (isFunctor(v)) {
|
if (isFunctor(v)) {
|
||||||
try {
|
try {
|
||||||
Value & functor = *v.attrs()->find(sFunctor)->value;
|
Value & functor = *v.attrs()->find(s.functor)->value;
|
||||||
Value * vp[] = {&v};
|
Value * vp[] = {&v};
|
||||||
Value partiallyApplied;
|
Value partiallyApplied;
|
||||||
// The first parameter is not user-provided, and may be
|
// The first parameter is not user-provided, and may be
|
||||||
|
|
@ -978,8 +919,8 @@ void EvalState::mkPos(Value & v, PosIdx p)
|
||||||
auto origin = positions.originOf(p);
|
auto origin = positions.originOf(p);
|
||||||
if (auto path = std::get_if<SourcePath>(&origin)) {
|
if (auto path = std::get_if<SourcePath>(&origin)) {
|
||||||
auto attrs = buildBindings(3);
|
auto attrs = buildBindings(3);
|
||||||
attrs.alloc(sFile).mkString(path->path.abs());
|
attrs.alloc(s.file).mkString(path->path.abs());
|
||||||
makePositionThunks(*this, p, attrs.alloc(sLine), attrs.alloc(sColumn));
|
makePositionThunks(*this, p, attrs.alloc(s.line), attrs.alloc(s.column));
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
} else
|
} else
|
||||||
v.mkNull();
|
v.mkNull();
|
||||||
|
|
@ -1245,7 +1186,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
dynamicEnv = &env2;
|
dynamicEnv = &env2;
|
||||||
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr;
|
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr;
|
||||||
|
|
||||||
AttrDefs::iterator overrides = attrs.find(state.sOverrides);
|
AttrDefs::iterator overrides = attrs.find(state.s.overrides);
|
||||||
bool hasOverrides = overrides != attrs.end();
|
bool hasOverrides = overrides != attrs.end();
|
||||||
|
|
||||||
/* The recursive attributes are evaluated in the new
|
/* The recursive attributes are evaluated in the new
|
||||||
|
|
@ -1717,7 +1658,7 @@ void EvalState::callFunction(Value & fun, std::span<Value *> args, Value & vRes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (vCur.type() == nAttrs && (functor = vCur.attrs()->get(sFunctor))) {
|
else if (vCur.type() == nAttrs && (functor = vCur.attrs()->get(s.functor))) {
|
||||||
/* 'vCur' may be allocated on the stack of the calling
|
/* 'vCur' may be allocated on the stack of the calling
|
||||||
function, but for functors we may keep a reference, so
|
function, but for functors we may keep a reference, so
|
||||||
heap-allocate a copy and use that instead. */
|
heap-allocate a copy and use that instead. */
|
||||||
|
|
@ -1779,7 +1720,7 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res
|
||||||
forceValue(fun, pos);
|
forceValue(fun, pos);
|
||||||
|
|
||||||
if (fun.type() == nAttrs) {
|
if (fun.type() == nAttrs) {
|
||||||
auto found = fun.attrs()->find(sFunctor);
|
auto found = fun.attrs()->find(s.functor);
|
||||||
if (found != fun.attrs()->end()) {
|
if (found != fun.attrs()->end()) {
|
||||||
Value * v = allocValue();
|
Value * v = allocValue();
|
||||||
callFunction(*found->value, fun, *v, pos);
|
callFunction(*found->value, fun, *v, pos);
|
||||||
|
|
@ -2241,7 +2182,7 @@ Bindings::const_iterator EvalState::getAttr(Symbol attrSym, const Bindings * att
|
||||||
|
|
||||||
bool EvalState::isFunctor(const Value & fun) const
|
bool EvalState::isFunctor(const Value & fun) const
|
||||||
{
|
{
|
||||||
return fun.type() == nAttrs && fun.attrs()->find(sFunctor) != fun.attrs()->end();
|
return fun.type() == nAttrs && fun.attrs()->find(s.functor) != fun.attrs()->end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx)
|
void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||||
|
|
@ -2310,7 +2251,7 @@ bool EvalState::isDerivation(Value & v)
|
||||||
{
|
{
|
||||||
if (v.type() != nAttrs)
|
if (v.type() != nAttrs)
|
||||||
return false;
|
return false;
|
||||||
auto i = v.attrs()->get(sType);
|
auto i = v.attrs()->get(s.type);
|
||||||
if (!i)
|
if (!i)
|
||||||
return false;
|
return false;
|
||||||
forceValue(*i->value, i->pos);
|
forceValue(*i->value, i->pos);
|
||||||
|
|
@ -2322,7 +2263,7 @@ bool EvalState::isDerivation(Value & v)
|
||||||
std::optional<std::string>
|
std::optional<std::string>
|
||||||
EvalState::tryAttrsToString(const PosIdx pos, Value & v, NixStringContext & context, bool coerceMore, bool copyToStore)
|
EvalState::tryAttrsToString(const PosIdx pos, Value & v, NixStringContext & context, bool coerceMore, bool copyToStore)
|
||||||
{
|
{
|
||||||
auto i = v.attrs()->find(sToString);
|
auto i = v.attrs()->find(s.toString);
|
||||||
if (i != v.attrs()->end()) {
|
if (i != v.attrs()->end()) {
|
||||||
Value v1;
|
Value v1;
|
||||||
callFunction(*i->value, v, v1, pos);
|
callFunction(*i->value, v, v1, pos);
|
||||||
|
|
@ -2368,7 +2309,7 @@ BackedStringView EvalState::coerceToString(
|
||||||
auto maybeString = tryAttrsToString(pos, v, context, coerceMore, copyToStore);
|
auto maybeString = tryAttrsToString(pos, v, context, coerceMore, copyToStore);
|
||||||
if (maybeString)
|
if (maybeString)
|
||||||
return std::move(*maybeString);
|
return std::move(*maybeString);
|
||||||
auto i = v.attrs()->find(sOutPath);
|
auto i = v.attrs()->find(s.outPath);
|
||||||
if (i == v.attrs()->end()) {
|
if (i == v.attrs()->end()) {
|
||||||
error<TypeError>(
|
error<TypeError>(
|
||||||
"cannot coerce %1% to a string: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
"cannot coerce %1% to a string: %2%", showType(v), ValuePrinter(*this, v, errorPrintOptions))
|
||||||
|
|
@ -2475,7 +2416,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext
|
||||||
/* Similarly, handle __toString where the result may be a path
|
/* Similarly, handle __toString where the result may be a path
|
||||||
value. */
|
value. */
|
||||||
if (v.type() == nAttrs) {
|
if (v.type() == nAttrs) {
|
||||||
auto i = v.attrs()->find(sToString);
|
auto i = v.attrs()->find(s.toString);
|
||||||
if (i != v.attrs()->end()) {
|
if (i != v.attrs()->end()) {
|
||||||
Value v1;
|
Value v1;
|
||||||
callFunction(*i->value, v, v1, pos);
|
callFunction(*i->value, v, v1, pos);
|
||||||
|
|
@ -2665,8 +2606,8 @@ void EvalState::assertEqValues(Value & v1, Value & v2, const PosIdx pos, std::st
|
||||||
|
|
||||||
case nAttrs: {
|
case nAttrs: {
|
||||||
if (isDerivation(v1) && isDerivation(v2)) {
|
if (isDerivation(v1) && isDerivation(v2)) {
|
||||||
auto i = v1.attrs()->get(sOutPath);
|
auto i = v1.attrs()->get(s.outPath);
|
||||||
auto j = v2.attrs()->get(sOutPath);
|
auto j = v2.attrs()->get(s.outPath);
|
||||||
if (i && j) {
|
if (i && j) {
|
||||||
try {
|
try {
|
||||||
assertEqValues(*i->value, *j->value, pos, errorCtx);
|
assertEqValues(*i->value, *j->value, pos, errorCtx);
|
||||||
|
|
@ -2819,8 +2760,8 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
||||||
/* If both sets denote a derivation (type = "derivation"),
|
/* If both sets denote a derivation (type = "derivation"),
|
||||||
then compare their outPaths. */
|
then compare their outPaths. */
|
||||||
if (isDerivation(v1) && isDerivation(v2)) {
|
if (isDerivation(v1) && isDerivation(v2)) {
|
||||||
auto i = v1.attrs()->get(sOutPath);
|
auto i = v1.attrs()->get(s.outPath);
|
||||||
auto j = v2.attrs()->get(sOutPath);
|
auto j = v2.attrs()->get(s.outPath);
|
||||||
if (i && j)
|
if (i && j)
|
||||||
return eqValues(*i->value, *j->value, pos, errorCtx);
|
return eqValues(*i->value, *j->value, pos, errorCtx);
|
||||||
}
|
}
|
||||||
|
|
@ -3196,8 +3137,7 @@ Expr * EvalState::parse(
|
||||||
docComments = &it->second;
|
docComments = &it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = parseExprFromBuf(
|
auto result = parseExprFromBuf(text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS);
|
||||||
text, length, origin, basePath, symbols, settings, positions, *docComments, rootFS, exprSymbols);
|
|
||||||
|
|
||||||
result->bindVars(*this, staticEnv);
|
result->bindVars(*this, staticEnv);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ PackageInfo::PackageInfo(EvalState & state, ref<Store> store, const std::string
|
||||||
std::string PackageInfo::queryName() const
|
std::string PackageInfo::queryName() const
|
||||||
{
|
{
|
||||||
if (name == "" && attrs) {
|
if (name == "" && attrs) {
|
||||||
auto i = attrs->find(state->sName);
|
auto i = attrs->find(state->s.name);
|
||||||
if (i == attrs->end())
|
if (i == attrs->end())
|
||||||
state->error<TypeError>("derivation name missing").debugThrow();
|
state->error<TypeError>("derivation name missing").debugThrow();
|
||||||
name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
|
name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
|
||||||
|
|
@ -56,7 +56,7 @@ std::string PackageInfo::queryName() const
|
||||||
std::string PackageInfo::querySystem() const
|
std::string PackageInfo::querySystem() const
|
||||||
{
|
{
|
||||||
if (system == "" && attrs) {
|
if (system == "" && attrs) {
|
||||||
auto i = attrs->find(state->sSystem);
|
auto i = attrs->find(state->s.system);
|
||||||
system =
|
system =
|
||||||
i == attrs->end()
|
i == attrs->end()
|
||||||
? "unknown"
|
? "unknown"
|
||||||
|
|
@ -68,7 +68,7 @@ std::string PackageInfo::querySystem() const
|
||||||
std::optional<StorePath> PackageInfo::queryDrvPath() const
|
std::optional<StorePath> PackageInfo::queryDrvPath() const
|
||||||
{
|
{
|
||||||
if (!drvPath && attrs) {
|
if (!drvPath && attrs) {
|
||||||
if (auto i = attrs->get(state->sDrvPath)) {
|
if (auto i = attrs->get(state->s.drvPath)) {
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
auto found = state->coerceToStorePath(
|
auto found = state->coerceToStorePath(
|
||||||
i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
i->pos, *i->value, context, "while evaluating the 'drvPath' attribute of a derivation");
|
||||||
|
|
@ -95,7 +95,7 @@ StorePath PackageInfo::requireDrvPath() const
|
||||||
StorePath PackageInfo::queryOutPath() const
|
StorePath PackageInfo::queryOutPath() const
|
||||||
{
|
{
|
||||||
if (!outPath && attrs) {
|
if (!outPath && attrs) {
|
||||||
auto i = attrs->find(state->sOutPath);
|
auto i = attrs->find(state->s.outPath);
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
if (i != attrs->end())
|
if (i != attrs->end())
|
||||||
outPath = state->coerceToStorePath(
|
outPath = state->coerceToStorePath(
|
||||||
|
|
@ -111,7 +111,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
if (outputs.empty()) {
|
if (outputs.empty()) {
|
||||||
/* Get the ‘outputs’ list. */
|
/* Get the ‘outputs’ list. */
|
||||||
const Attr * i;
|
const Attr * i;
|
||||||
if (attrs && (i = attrs->get(state->sOutputs))) {
|
if (attrs && (i = attrs->get(state->s.outputs))) {
|
||||||
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... */
|
||||||
|
|
@ -127,7 +127,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
state->forceAttrs(*out->value, i->pos, "while evaluating an output of a derivation");
|
state->forceAttrs(*out->value, i->pos, "while evaluating an output of a derivation");
|
||||||
|
|
||||||
/* And evaluate its ‘outPath’ attribute. */
|
/* And evaluate its ‘outPath’ attribute. */
|
||||||
auto outPath = out->value->attrs()->get(state->sOutPath);
|
auto outPath = out->value->attrs()->get(state->s.outPath);
|
||||||
if (!outPath)
|
if (!outPath)
|
||||||
continue; // FIXME: throw error?
|
continue; // FIXME: throw error?
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
|
|
@ -146,7 +146,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
return outputs;
|
return outputs;
|
||||||
|
|
||||||
const Attr * i;
|
const Attr * i;
|
||||||
if (attrs && (i = attrs->get(state->sOutputSpecified))
|
if (attrs && (i = attrs->get(state->s.outputSpecified))
|
||||||
&& state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) {
|
&& state->forceBool(*i->value, i->pos, "while evaluating the 'outputSpecified' attribute of a derivation")) {
|
||||||
Outputs result;
|
Outputs result;
|
||||||
auto out = outputs.find(queryOutputName());
|
auto out = outputs.find(queryOutputName());
|
||||||
|
|
@ -181,7 +181,7 @@ PackageInfo::Outputs PackageInfo::queryOutputs(bool withPaths, bool onlyOutputsT
|
||||||
std::string PackageInfo::queryOutputName() const
|
std::string PackageInfo::queryOutputName() const
|
||||||
{
|
{
|
||||||
if (outputName == "" && attrs) {
|
if (outputName == "" && attrs) {
|
||||||
auto i = attrs->get(state->sOutputName);
|
auto i = attrs->get(state->s.outputName);
|
||||||
outputName =
|
outputName =
|
||||||
i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
|
i ? state->forceStringNoCtx(*i->value, noPos, "while evaluating the output name of a derivation") : "";
|
||||||
}
|
}
|
||||||
|
|
@ -194,7 +194,7 @@ const Bindings * PackageInfo::getMeta()
|
||||||
return meta;
|
return meta;
|
||||||
if (!attrs)
|
if (!attrs)
|
||||||
return 0;
|
return 0;
|
||||||
auto a = attrs->get(state->sMeta);
|
auto a = attrs->get(state->s.meta);
|
||||||
if (!a)
|
if (!a)
|
||||||
return 0;
|
return 0;
|
||||||
state->forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
|
state->forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
|
||||||
|
|
@ -221,7 +221,7 @@ bool PackageInfo::checkMeta(Value & v)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
} else if (v.type() == nAttrs) {
|
} else if (v.type() == nAttrs) {
|
||||||
if (v.attrs()->get(state->sOutPath))
|
if (v.attrs()->get(state->s.outPath))
|
||||||
return false;
|
return false;
|
||||||
for (auto & i : *v.attrs())
|
for (auto & i : *v.attrs())
|
||||||
if (!checkMeta(*i.value))
|
if (!checkMeta(*i.value))
|
||||||
|
|
@ -411,7 +411,7 @@ static void getDerivations(
|
||||||
should we recurse into it? => Only if it has a
|
should we recurse into it? => Only if it has a
|
||||||
`recurseForDerivations = true' attribute. */
|
`recurseForDerivations = true' attribute. */
|
||||||
if (i->value->type() == nAttrs) {
|
if (i->value->type() == nAttrs) {
|
||||||
auto j = i->value->attrs()->get(state.sRecurseForDerivations);
|
auto j = i->value->attrs()->get(state.s.recurseForDerivations);
|
||||||
if (j
|
if (j
|
||||||
&& state.forceBool(
|
&& state.forceBool(
|
||||||
*j->value, j->pos, "while evaluating the attribute `recurseForDerivations`"))
|
*j->value, j->pos, "while evaluating the attribute `recurseForDerivations`"))
|
||||||
|
|
|
||||||
|
|
@ -213,23 +213,100 @@ struct DebugTrace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StaticEvalSymbols
|
||||||
|
{
|
||||||
|
Symbol with, outPath, drvPath, type, meta, name, value, system, overrides, outputs, outputName, ignoreNulls, file,
|
||||||
|
line, column, functor, toString, right, wrong, structuredAttrs, json, allowedReferences, allowedRequisites,
|
||||||
|
disallowedReferences, disallowedRequisites, maxSize, maxClosureSize, builder, args, contentAddressed, impure,
|
||||||
|
outputHash, outputHashAlgo, outputHashMode, recurseForDerivations, description, self, epsilon, startSet,
|
||||||
|
operator_, key, path, prefix, outputSpecified;
|
||||||
|
|
||||||
|
Expr::AstSymbols exprSymbols;
|
||||||
|
|
||||||
|
static constexpr auto preallocate()
|
||||||
|
{
|
||||||
|
StaticSymbolTable alloc;
|
||||||
|
|
||||||
|
StaticEvalSymbols staticSymbols = {
|
||||||
|
.with = alloc.create("<with>"),
|
||||||
|
.outPath = alloc.create("outPath"),
|
||||||
|
.drvPath = alloc.create("drvPath"),
|
||||||
|
.type = alloc.create("type"),
|
||||||
|
.meta = alloc.create("meta"),
|
||||||
|
.name = alloc.create("name"),
|
||||||
|
.value = alloc.create("value"),
|
||||||
|
.system = alloc.create("system"),
|
||||||
|
.overrides = alloc.create("__overrides"),
|
||||||
|
.outputs = alloc.create("outputs"),
|
||||||
|
.outputName = alloc.create("outputName"),
|
||||||
|
.ignoreNulls = alloc.create("__ignoreNulls"),
|
||||||
|
.file = alloc.create("file"),
|
||||||
|
.line = alloc.create("line"),
|
||||||
|
.column = alloc.create("column"),
|
||||||
|
.functor = alloc.create("__functor"),
|
||||||
|
.toString = alloc.create("__toString"),
|
||||||
|
.right = alloc.create("right"),
|
||||||
|
.wrong = alloc.create("wrong"),
|
||||||
|
.structuredAttrs = alloc.create("__structuredAttrs"),
|
||||||
|
.json = alloc.create("__json"),
|
||||||
|
.allowedReferences = alloc.create("allowedReferences"),
|
||||||
|
.allowedRequisites = alloc.create("allowedRequisites"),
|
||||||
|
.disallowedReferences = alloc.create("disallowedReferences"),
|
||||||
|
.disallowedRequisites = alloc.create("disallowedRequisites"),
|
||||||
|
.maxSize = alloc.create("maxSize"),
|
||||||
|
.maxClosureSize = alloc.create("maxClosureSize"),
|
||||||
|
.builder = alloc.create("builder"),
|
||||||
|
.args = alloc.create("args"),
|
||||||
|
.contentAddressed = alloc.create("__contentAddressed"),
|
||||||
|
.impure = alloc.create("__impure"),
|
||||||
|
.outputHash = alloc.create("outputHash"),
|
||||||
|
.outputHashAlgo = alloc.create("outputHashAlgo"),
|
||||||
|
.outputHashMode = alloc.create("outputHashMode"),
|
||||||
|
.recurseForDerivations = alloc.create("recurseForDerivations"),
|
||||||
|
.description = alloc.create("description"),
|
||||||
|
.self = alloc.create("self"),
|
||||||
|
.epsilon = alloc.create(""),
|
||||||
|
.startSet = alloc.create("startSet"),
|
||||||
|
.operator_ = alloc.create("operator"),
|
||||||
|
.key = alloc.create("key"),
|
||||||
|
.path = alloc.create("path"),
|
||||||
|
.prefix = alloc.create("prefix"),
|
||||||
|
.outputSpecified = alloc.create("outputSpecified"),
|
||||||
|
.exprSymbols = {
|
||||||
|
.sub = alloc.create("__sub"),
|
||||||
|
.lessThan = alloc.create("__lessThan"),
|
||||||
|
.mul = alloc.create("__mul"),
|
||||||
|
.div = alloc.create("__div"),
|
||||||
|
.or_ = alloc.create("or"),
|
||||||
|
.findFile = alloc.create("__findFile"),
|
||||||
|
.nixPath = alloc.create("__nixPath"),
|
||||||
|
.body = alloc.create("body"),
|
||||||
|
}};
|
||||||
|
|
||||||
|
return std::pair{staticSymbols, alloc};
|
||||||
|
}
|
||||||
|
|
||||||
|
static consteval StaticEvalSymbols create()
|
||||||
|
{
|
||||||
|
return preallocate().first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr StaticSymbolTable staticSymbolTable()
|
||||||
|
{
|
||||||
|
return preallocate().second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class EvalState : public std::enable_shared_from_this<EvalState>
|
class EvalState : public std::enable_shared_from_this<EvalState>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static constexpr StaticEvalSymbols s = StaticEvalSymbols::create();
|
||||||
|
|
||||||
const fetchers::Settings & fetchSettings;
|
const fetchers::Settings & fetchSettings;
|
||||||
const EvalSettings & settings;
|
const EvalSettings & settings;
|
||||||
SymbolTable symbols;
|
SymbolTable symbols;
|
||||||
PosTable positions;
|
PosTable positions;
|
||||||
|
|
||||||
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue, sSystem, sOverrides, sOutputs, sOutputName,
|
|
||||||
sIgnoreNulls, sFile, sLine, sColumn, sFunctor, sToString, sRight, sWrong, sStructuredAttrs, sJson,
|
|
||||||
sAllowedReferences, sAllowedRequisites, sDisallowedReferences, sDisallowedRequisites, sMaxSize, sMaxClosureSize,
|
|
||||||
sBuilder, sArgs, sContentAddressed, sImpure, sOutputHash, sOutputHashAlgo, sOutputHashMode,
|
|
||||||
sRecurseForDerivations, sDescription, sSelf, sEpsilon, sStartSet, sOperator, sKey, sPath, sPrefix,
|
|
||||||
sOutputSpecified;
|
|
||||||
|
|
||||||
const Expr::AstSymbols exprSymbols;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set, force copying files to the Nix store even if they
|
* If set, force copying files to the Nix store even if they
|
||||||
* already exist there.
|
* already exist there.
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ struct ParserState
|
||||||
SourcePath basePath;
|
SourcePath basePath;
|
||||||
PosTable::Origin origin;
|
PosTable::Origin origin;
|
||||||
const ref<SourceAccessor> rootFS;
|
const ref<SourceAccessor> rootFS;
|
||||||
const Expr::AstSymbols & s;
|
static constexpr Expr::AstSymbols s = StaticEvalSymbols::create().exprSymbols;
|
||||||
const EvalSettings & settings;
|
const EvalSettings & settings;
|
||||||
|
|
||||||
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StaticSymbolTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbols have the property that they can be compared efficiently
|
* Symbols have the property that they can be compared efficiently
|
||||||
* (using an equality test), because the symbol table stores only one
|
* (using an equality test), because the symbol table stores only one
|
||||||
|
|
@ -37,36 +39,29 @@ class Symbol
|
||||||
{
|
{
|
||||||
friend class SymbolStr;
|
friend class SymbolStr;
|
||||||
friend class SymbolTable;
|
friend class SymbolTable;
|
||||||
|
friend class StaticSymbolTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
|
||||||
explicit Symbol(uint32_t id) noexcept
|
explicit constexpr Symbol(uint32_t id) noexcept
|
||||||
: id(id)
|
: id(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Symbol() noexcept
|
constexpr Symbol() noexcept
|
||||||
: id(0)
|
: id(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[gnu::always_inline]]
|
[[gnu::always_inline]]
|
||||||
explicit operator bool() const noexcept
|
constexpr explicit operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return id > 0;
|
return id > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator<=>(const Symbol other) const noexcept
|
constexpr auto operator<=>(const Symbol & other) const noexcept = default;
|
||||||
{
|
|
||||||
return id <=> other.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const Symbol other) const noexcept
|
|
||||||
{
|
|
||||||
return id == other.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class std::hash<Symbol>;
|
friend class std::hash<Symbol>;
|
||||||
};
|
};
|
||||||
|
|
@ -210,6 +205,39 @@ public:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SymbolTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience class to statically assign symbol identifiers at compile-time.
|
||||||
|
*/
|
||||||
|
class StaticSymbolTable
|
||||||
|
{
|
||||||
|
static constexpr std::size_t maxSize = 1024;
|
||||||
|
|
||||||
|
struct StaticSymbolInfo
|
||||||
|
{
|
||||||
|
std::string_view str;
|
||||||
|
Symbol sym;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<StaticSymbolInfo, maxSize> symbols;
|
||||||
|
std::size_t size = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr StaticSymbolTable() = default;
|
||||||
|
|
||||||
|
constexpr Symbol create(std::string_view str)
|
||||||
|
{
|
||||||
|
/* No need to check bounds because out of bounds access is
|
||||||
|
a compilation error. */
|
||||||
|
auto sym = Symbol(size + 1); //< +1 because Symbol with id = 0 is reserved
|
||||||
|
symbols[size++] = {str, sym};
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyIntoSymbolTable(SymbolTable & symtab) const;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Symbol table used by the parser and evaluator to represent and look
|
* Symbol table used by the parser and evaluator to represent and look
|
||||||
* up identifiers and attributes efficiently.
|
* up identifiers and attributes efficiently.
|
||||||
|
|
@ -232,6 +260,10 @@ private:
|
||||||
boost::unordered_flat_set<SymbolStr, SymbolStr::Hash, SymbolStr::Equal> symbols{SymbolStr::chunkSize};
|
boost::unordered_flat_set<SymbolStr, SymbolStr::Hash, SymbolStr::Equal> symbols{SymbolStr::chunkSize};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
SymbolTable(const StaticSymbolTable & staticSymtab)
|
||||||
|
{
|
||||||
|
staticSymtab.copyIntoSymbolTable(*this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a string into a symbol.
|
* Converts a string into a symbol.
|
||||||
|
|
@ -276,6 +308,16 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void StaticSymbolTable::copyIntoSymbolTable(SymbolTable & symtab) const
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < size; ++i) {
|
||||||
|
auto [str, staticSym] = symbols[i];
|
||||||
|
auto sym = symtab.create(str);
|
||||||
|
if (sym != staticSym) [[unlikely]]
|
||||||
|
unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,7 @@ Expr * parseExprFromBuf(
|
||||||
const EvalSettings & settings,
|
const EvalSettings & settings,
|
||||||
PosTable & positions,
|
PosTable & positions,
|
||||||
DocCommentMap & docComments,
|
DocCommentMap & docComments,
|
||||||
const ref<SourceAccessor> rootFS,
|
const ref<SourceAccessor> rootFS);
|
||||||
const Expr::AstSymbols & astSymbols);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -542,8 +541,7 @@ Expr * parseExprFromBuf(
|
||||||
const EvalSettings & settings,
|
const EvalSettings & settings,
|
||||||
PosTable & positions,
|
PosTable & positions,
|
||||||
DocCommentMap & docComments,
|
DocCommentMap & docComments,
|
||||||
const ref<SourceAccessor> rootFS,
|
const ref<SourceAccessor> rootFS)
|
||||||
const Expr::AstSymbols & astSymbols)
|
|
||||||
{
|
{
|
||||||
yyscan_t scanner;
|
yyscan_t scanner;
|
||||||
LexerState lexerState {
|
LexerState lexerState {
|
||||||
|
|
@ -558,7 +556,6 @@ Expr * parseExprFromBuf(
|
||||||
.basePath = basePath,
|
.basePath = basePath,
|
||||||
.origin = lexerState.origin,
|
.origin = lexerState.origin,
|
||||||
.rootFS = rootFS,
|
.rootFS = rootFS,
|
||||||
.s = astSymbols,
|
|
||||||
.settings = settings,
|
.settings = settings,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -214,20 +214,20 @@ void derivationToValue(
|
||||||
auto path2 = path.path.abs();
|
auto path2 = path.path.abs();
|
||||||
Derivation drv = state.store->readDerivation(storePath);
|
Derivation drv = state.store->readDerivation(storePath);
|
||||||
auto attrs = state.buildBindings(3 + drv.outputs.size());
|
auto attrs = state.buildBindings(3 + drv.outputs.size());
|
||||||
attrs.alloc(state.sDrvPath)
|
attrs.alloc(state.s.drvPath)
|
||||||
.mkString(
|
.mkString(
|
||||||
path2,
|
path2,
|
||||||
{
|
{
|
||||||
NixStringContextElem::DrvDeep{.drvPath = storePath},
|
NixStringContextElem::DrvDeep{.drvPath = storePath},
|
||||||
});
|
});
|
||||||
attrs.alloc(state.sName).mkString(drv.env["name"]);
|
attrs.alloc(state.s.name).mkString(drv.env["name"]);
|
||||||
|
|
||||||
auto list = state.buildList(drv.outputs.size());
|
auto list = state.buildList(drv.outputs.size());
|
||||||
for (const auto & [i, o] : enumerate(drv.outputs)) {
|
for (const auto & [i, o] : enumerate(drv.outputs)) {
|
||||||
mkOutputString(state, attrs, storePath, o);
|
mkOutputString(state, attrs, storePath, o);
|
||||||
(list[i] = state.allocValue())->mkString(o.first);
|
(list[i] = state.allocValue())->mkString(o.first);
|
||||||
}
|
}
|
||||||
attrs.alloc(state.sOutputs).mkList(list);
|
attrs.alloc(state.s.outputs).mkList(list);
|
||||||
|
|
||||||
auto w = state.allocValue();
|
auto w = state.allocValue();
|
||||||
w->mkAttrs(attrs);
|
w->mkAttrs(attrs);
|
||||||
|
|
@ -731,7 +731,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value ** ar
|
||||||
|
|
||||||
/* Get the start set. */
|
/* Get the start set. */
|
||||||
auto startSet = state.getAttr(
|
auto startSet = state.getAttr(
|
||||||
state.sStartSet, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure");
|
state.s.startSet, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure");
|
||||||
|
|
||||||
state.forceList(
|
state.forceList(
|
||||||
*startSet->value,
|
*startSet->value,
|
||||||
|
|
@ -749,7 +749,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value ** ar
|
||||||
|
|
||||||
/* Get the operator. */
|
/* Get the operator. */
|
||||||
auto op = state.getAttr(
|
auto op = state.getAttr(
|
||||||
state.sOperator, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure");
|
state.s.operator_, args[0]->attrs(), "in the attrset passed as argument to builtins.genericClosure");
|
||||||
state.forceFunction(
|
state.forceFunction(
|
||||||
*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure");
|
*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure");
|
||||||
|
|
||||||
|
|
@ -771,7 +771,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value ** ar
|
||||||
"while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure");
|
"while evaluating one of the elements generated by (or initially passed to) builtins.genericClosure");
|
||||||
|
|
||||||
auto key = state.getAttr(
|
auto key = state.getAttr(
|
||||||
state.sKey,
|
state.s.key,
|
||||||
e->attrs(),
|
e->attrs(),
|
||||||
"in one of the attrsets generated by (or initially passed to) builtins.genericClosure");
|
"in one of the attrsets generated by (or initially passed to) builtins.genericClosure");
|
||||||
state.forceValue(*key->value, noPos);
|
state.forceValue(*key->value, noPos);
|
||||||
|
|
@ -1076,11 +1076,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.sValue, args[0]);
|
attrs.insert(state.s.value, args[0]);
|
||||||
attrs.insert(state.symbols.create("success"), &state.vTrue);
|
attrs.insert(state.symbols.create("success"), &state.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.sValue, &state.vFalse);
|
attrs.insert(state.s.value, &state.vFalse);
|
||||||
attrs.insert(state.symbols.create("success"), &state.vFalse);
|
attrs.insert(state.symbols.create("success"), &state.vFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1292,7 +1292,8 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value **
|
||||||
auto attrs = args[0]->attrs();
|
auto attrs = args[0]->attrs();
|
||||||
|
|
||||||
/* Figure out the name first (for stack backtraces). */
|
/* Figure out the name first (for stack backtraces). */
|
||||||
auto nameAttr = state.getAttr(state.sName, attrs, "in the attrset passed as argument to builtins.derivationStrict");
|
auto nameAttr =
|
||||||
|
state.getAttr(state.s.name, attrs, "in the attrset passed as argument to builtins.derivationStrict");
|
||||||
|
|
||||||
std::string_view drvName;
|
std::string_view drvName;
|
||||||
try {
|
try {
|
||||||
|
|
@ -1366,7 +1367,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
std::optional<StructuredAttrs> jsonObject;
|
std::optional<StructuredAttrs> jsonObject;
|
||||||
auto pos = v.determinePos(noPos);
|
auto pos = v.determinePos(noPos);
|
||||||
auto attr = attrs->find(state.sStructuredAttrs);
|
auto attr = attrs->find(state.s.structuredAttrs);
|
||||||
if (attr != attrs->end()
|
if (attr != attrs->end()
|
||||||
&& state.forceBool(
|
&& state.forceBool(
|
||||||
*attr->value,
|
*attr->value,
|
||||||
|
|
@ -1377,7 +1378,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
|
|
||||||
/* Check whether null attributes should be ignored. */
|
/* Check whether null attributes should be ignored. */
|
||||||
bool ignoreNulls = false;
|
bool ignoreNulls = false;
|
||||||
attr = attrs->find(state.sIgnoreNulls);
|
attr = attrs->find(state.s.ignoreNulls);
|
||||||
if (attr != attrs->end())
|
if (attr != attrs->end())
|
||||||
ignoreNulls = state.forceBool(
|
ignoreNulls = state.forceBool(
|
||||||
*attr->value,
|
*attr->value,
|
||||||
|
|
@ -1401,7 +1402,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
outputs.insert("out");
|
outputs.insert("out");
|
||||||
|
|
||||||
for (auto & i : attrs->lexicographicOrder(state.symbols)) {
|
for (auto & i : attrs->lexicographicOrder(state.symbols)) {
|
||||||
if (i->name == state.sIgnoreNulls)
|
if (i->name == state.s.ignoreNulls)
|
||||||
continue;
|
continue;
|
||||||
auto key = state.symbols[i->name];
|
auto key = state.symbols[i->name];
|
||||||
vomit("processing attribute '%1%'", key);
|
vomit("processing attribute '%1%'", key);
|
||||||
|
|
@ -1453,19 +1454,19 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->name == state.sContentAddressed && state.forceBool(*i->value, pos, context_below)) {
|
if (i->name == state.s.contentAddressed && state.forceBool(*i->value, pos, context_below)) {
|
||||||
contentAddressed = true;
|
contentAddressed = true;
|
||||||
experimentalFeatureSettings.require(Xp::CaDerivations);
|
experimentalFeatureSettings.require(Xp::CaDerivations);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (i->name == state.sImpure && state.forceBool(*i->value, pos, context_below)) {
|
else if (i->name == state.s.impure && state.forceBool(*i->value, pos, context_below)) {
|
||||||
isImpure = true;
|
isImpure = true;
|
||||||
experimentalFeatureSettings.require(Xp::ImpureDerivations);
|
experimentalFeatureSettings.require(Xp::ImpureDerivations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The `args' attribute is special: it supplies the
|
/* The `args' attribute is special: it supplies the
|
||||||
command-line arguments to the builder. */
|
command-line arguments to the builder. */
|
||||||
else if (i->name == state.sArgs) {
|
else if (i->name == state.s.args) {
|
||||||
state.forceList(*i->value, pos, context_below);
|
state.forceList(*i->value, pos, context_below);
|
||||||
for (auto elem : i->value->listView()) {
|
for (auto elem : i->value->listView()) {
|
||||||
auto s = state
|
auto s = state
|
||||||
|
|
@ -1482,22 +1483,22 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
|
|
||||||
if (jsonObject) {
|
if (jsonObject) {
|
||||||
|
|
||||||
if (i->name == state.sStructuredAttrs)
|
if (i->name == state.s.structuredAttrs)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
jsonObject->structuredAttrs.emplace(key, printValueAsJSON(state, true, *i->value, pos, context));
|
jsonObject->structuredAttrs.emplace(key, printValueAsJSON(state, true, *i->value, pos, context));
|
||||||
|
|
||||||
if (i->name == state.sBuilder)
|
if (i->name == state.s.builder)
|
||||||
drv.builder = state.forceString(*i->value, context, pos, context_below);
|
drv.builder = state.forceString(*i->value, context, pos, context_below);
|
||||||
else if (i->name == state.sSystem)
|
else if (i->name == state.s.system)
|
||||||
drv.platform = state.forceStringNoCtx(*i->value, pos, context_below);
|
drv.platform = state.forceStringNoCtx(*i->value, pos, context_below);
|
||||||
else if (i->name == state.sOutputHash)
|
else if (i->name == state.s.outputHash)
|
||||||
outputHash = state.forceStringNoCtx(*i->value, pos, context_below);
|
outputHash = state.forceStringNoCtx(*i->value, pos, context_below);
|
||||||
else if (i->name == state.sOutputHashAlgo)
|
else if (i->name == state.s.outputHashAlgo)
|
||||||
outputHashAlgo = parseHashAlgoOpt(state.forceStringNoCtx(*i->value, pos, context_below));
|
outputHashAlgo = parseHashAlgoOpt(state.forceStringNoCtx(*i->value, pos, context_below));
|
||||||
else if (i->name == state.sOutputHashMode)
|
else if (i->name == state.s.outputHashMode)
|
||||||
handleHashMode(state.forceStringNoCtx(*i->value, pos, context_below));
|
handleHashMode(state.forceStringNoCtx(*i->value, pos, context_below));
|
||||||
else if (i->name == state.sOutputs) {
|
else if (i->name == state.s.outputs) {
|
||||||
/* 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;
|
||||||
|
|
@ -1506,51 +1507,51 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
handleOutputs(ss);
|
handleOutputs(ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->name == state.sAllowedReferences)
|
if (i->name == state.s.allowedReferences)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks.<output>.allowedReferences' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks.<output>.allowedReferences' instead",
|
||||||
drvName);
|
drvName);
|
||||||
if (i->name == state.sAllowedRequisites)
|
if (i->name == state.s.allowedRequisites)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks.<output>.allowedRequisites' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks.<output>.allowedRequisites' instead",
|
||||||
drvName);
|
drvName);
|
||||||
if (i->name == state.sDisallowedReferences)
|
if (i->name == state.s.disallowedReferences)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks.<output>.disallowedReferences' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks.<output>.disallowedReferences' instead",
|
||||||
drvName);
|
drvName);
|
||||||
if (i->name == state.sDisallowedRequisites)
|
if (i->name == state.s.disallowedRequisites)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks.<output>.disallowedRequisites' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks.<output>.disallowedRequisites' instead",
|
||||||
drvName);
|
drvName);
|
||||||
if (i->name == state.sMaxSize)
|
if (i->name == state.s.maxSize)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks.<output>.maxSize' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks.<output>.maxSize' instead",
|
||||||
drvName);
|
drvName);
|
||||||
if (i->name == state.sMaxClosureSize)
|
if (i->name == state.s.maxClosureSize)
|
||||||
warn(
|
warn(
|
||||||
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks.<output>.maxClosureSize' instead",
|
"In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks.<output>.maxClosureSize' instead",
|
||||||
drvName);
|
drvName);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
auto s = state.coerceToString(pos, *i->value, context, context_below, true).toOwned();
|
auto s = state.coerceToString(pos, *i->value, context, context_below, true).toOwned();
|
||||||
if (i->name == state.sJson) {
|
if (i->name == state.s.json) {
|
||||||
warn(
|
warn(
|
||||||
"In derivation '%s': setting structured attributes via '__json' is deprecated, and may be disallowed in future versions of Nix. Set '__structuredAttrs = true' instead.",
|
"In derivation '%s': setting structured attributes via '__json' is deprecated, and may be disallowed in future versions of Nix. Set '__structuredAttrs = true' instead.",
|
||||||
drvName);
|
drvName);
|
||||||
drv.structuredAttrs = StructuredAttrs::parse(s);
|
drv.structuredAttrs = StructuredAttrs::parse(s);
|
||||||
} else {
|
} else {
|
||||||
drv.env.emplace(key, s);
|
drv.env.emplace(key, s);
|
||||||
if (i->name == state.sBuilder)
|
if (i->name == state.s.builder)
|
||||||
drv.builder = std::move(s);
|
drv.builder = std::move(s);
|
||||||
else if (i->name == state.sSystem)
|
else if (i->name == state.s.system)
|
||||||
drv.platform = std::move(s);
|
drv.platform = std::move(s);
|
||||||
else if (i->name == state.sOutputHash)
|
else if (i->name == state.s.outputHash)
|
||||||
outputHash = std::move(s);
|
outputHash = std::move(s);
|
||||||
else if (i->name == state.sOutputHashAlgo)
|
else if (i->name == state.s.outputHashAlgo)
|
||||||
outputHashAlgo = parseHashAlgoOpt(s);
|
outputHashAlgo = parseHashAlgoOpt(s);
|
||||||
else if (i->name == state.sOutputHashMode)
|
else if (i->name == state.s.outputHashMode)
|
||||||
handleHashMode(s);
|
handleHashMode(s);
|
||||||
else if (i->name == state.sOutputs)
|
else if (i->name == state.s.outputs)
|
||||||
handleOutputs(tokenizeString<Strings>(s));
|
handleOutputs(tokenizeString<Strings>(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1722,7 +1723,7 @@ static void derivationStrictInternal(EvalState & state, std::string_view drvName
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = state.buildBindings(1 + drv.outputs.size());
|
auto result = state.buildBindings(1 + drv.outputs.size());
|
||||||
result.alloc(state.sDrvPath)
|
result.alloc(state.s.drvPath)
|
||||||
.mkString(
|
.mkString(
|
||||||
drvPathS,
|
drvPathS,
|
||||||
{
|
{
|
||||||
|
|
@ -2006,14 +2007,14 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value ** args, Va
|
||||||
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;
|
||||||
auto i = v2->attrs()->find(state.sPrefix);
|
auto i = v2->attrs()->find(state.s.prefix);
|
||||||
if (i != v2->attrs()->end())
|
if (i != v2->attrs()->end())
|
||||||
prefix = state.forceStringNoCtx(
|
prefix = state.forceStringNoCtx(
|
||||||
*i->value,
|
*i->value,
|
||||||
pos,
|
pos,
|
||||||
"while evaluating the `prefix` attribute of an element of the list passed to builtins.findFile");
|
"while evaluating the `prefix` attribute of an element of the list passed to builtins.findFile");
|
||||||
|
|
||||||
i = state.getAttr(state.sPath, v2->attrs(), "in an element of the __nixPath");
|
i = state.getAttr(state.s.path, v2->attrs(), "in an element of the __nixPath");
|
||||||
|
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
auto path =
|
auto path =
|
||||||
|
|
@ -2786,7 +2787,7 @@ static void prim_path(EvalState & state, const PosIdx pos, Value ** args, Value
|
||||||
if (n == "path")
|
if (n == "path")
|
||||||
path.emplace(state.coerceToPath(
|
path.emplace(state.coerceToPath(
|
||||||
attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'"));
|
attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'"));
|
||||||
else if (attr.name == state.sName)
|
else if (attr.name == state.s.name)
|
||||||
name = state.forceStringNoCtx(
|
name = state.forceStringNoCtx(
|
||||||
*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.path");
|
*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.path");
|
||||||
else if (n == "filter")
|
else if (n == "filter")
|
||||||
|
|
@ -3105,7 +3106,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value ** args,
|
||||||
for (const auto & [n, v2] : enumerate(listView)) {
|
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.s.name, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||||
|
|
||||||
auto name = state.forceStringNoCtx(
|
auto name = state.forceStringNoCtx(
|
||||||
*j->value,
|
*j->value,
|
||||||
|
|
@ -3132,7 +3133,7 @@ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value ** args,
|
||||||
// Note that .value is actually a Value * *; see earlier comments
|
// Note that .value is actually a Value * *; see earlier comments
|
||||||
Value * v2 = *std::bit_cast<ElemPtr>(attr.value);
|
Value * v2 = *std::bit_cast<ElemPtr>(attr.value);
|
||||||
|
|
||||||
auto j = state.getAttr(state.sValue, v2->attrs(), "in a {name=...; value=...;} pair");
|
auto j = state.getAttr(state.s.value, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||||
prev = attr.name;
|
prev = attr.name;
|
||||||
bindings.push_back({prev, j->value, j->pos});
|
bindings.push_back({prev, j->value, j->pos});
|
||||||
}
|
}
|
||||||
|
|
@ -3948,13 +3949,13 @@ static void prim_partition(EvalState & state, const PosIdx pos, Value ** args, V
|
||||||
auto rlist = state.buildList(rsize);
|
auto rlist = state.buildList(rsize);
|
||||||
if (rsize)
|
if (rsize)
|
||||||
memcpy(rlist.elems, right.data(), sizeof(Value *) * rsize);
|
memcpy(rlist.elems, right.data(), sizeof(Value *) * rsize);
|
||||||
attrs.alloc(state.sRight).mkList(rlist);
|
attrs.alloc(state.s.right).mkList(rlist);
|
||||||
|
|
||||||
auto wsize = wrong.size();
|
auto wsize = wrong.size();
|
||||||
auto wlist = state.buildList(wsize);
|
auto wlist = state.buildList(wsize);
|
||||||
if (wsize)
|
if (wsize)
|
||||||
memcpy(wlist.elems, wrong.data(), sizeof(Value *) * wsize);
|
memcpy(wlist.elems, wrong.data(), sizeof(Value *) * wsize);
|
||||||
attrs.alloc(state.sWrong).mkList(wlist);
|
attrs.alloc(state.s.wrong).mkList(wlist);
|
||||||
|
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
@ -4873,7 +4874,7 @@ static void prim_parseDrvName(EvalState & state, const PosIdx pos, Value ** args
|
||||||
state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.parseDrvName");
|
state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.parseDrvName");
|
||||||
DrvName parsed(name);
|
DrvName parsed(name);
|
||||||
auto attrs = state.buildBindings(2);
|
auto attrs = state.buildBindings(2);
|
||||||
attrs.alloc(state.sName).mkString(parsed.name);
|
attrs.alloc(state.s.name).mkString(parsed.name);
|
||||||
attrs.alloc("version").mkString(parsed.version);
|
attrs.alloc("version").mkString(parsed.version);
|
||||||
v.mkAttrs(attrs);
|
v.mkAttrs(attrs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@ static void prim_getContext(EvalState & state, const PosIdx pos, Value ** args,
|
||||||
auto list = state.buildList(info.second.outputs.size());
|
auto list = state.buildList(info.second.outputs.size());
|
||||||
for (const auto & [i, output] : enumerate(info.second.outputs))
|
for (const auto & [i, output] : enumerate(info.second.outputs))
|
||||||
(list[i] = state.allocValue())->mkString(output);
|
(list[i] = state.allocValue())->mkString(output);
|
||||||
infoAttrs.alloc(state.sOutputs).mkList(list);
|
infoAttrs.alloc(state.s.outputs).mkList(list);
|
||||||
}
|
}
|
||||||
attrs.alloc(state.store->printStorePath(info.first)).mkAttrs(infoAttrs);
|
attrs.alloc(state.store->printStorePath(info.first)).mkAttrs(infoAttrs);
|
||||||
}
|
}
|
||||||
|
|
@ -300,7 +300,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value ** arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto attr = i.value->attrs()->get(state.sOutputs)) {
|
if (auto attr = i.value->attrs()->get(state.s.outputs)) {
|
||||||
state.forceList(*attr->value, attr->pos, "while evaluating the `outputs` attribute of a string context");
|
state.forceList(*attr->value, attr->pos, "while evaluating the `outputs` attribute of a string context");
|
||||||
if (attr->value->listSize() && !isDerivation(name)) {
|
if (attr->value->listSize() && !isDerivation(name)) {
|
||||||
state
|
state
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value ** ar
|
||||||
auto [storePath, input2] = input.fetchToStore(state.store);
|
auto [storePath, input2] = input.fetchToStore(state.store);
|
||||||
|
|
||||||
auto attrs2 = state.buildBindings(8);
|
auto attrs2 = state.buildBindings(8);
|
||||||
state.mkStorePathString(storePath, attrs2.alloc(state.sOutPath));
|
state.mkStorePathString(storePath, attrs2.alloc(state.s.outPath));
|
||||||
if (input2.getRef())
|
if (input2.getRef())
|
||||||
attrs2.alloc("branch").mkString(*input2.getRef());
|
attrs2.alloc("branch").mkString(*input2.getRef());
|
||||||
// Backward compatibility: set 'rev' to
|
// Backward compatibility: set 'rev' to
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ void emitTreeAttrs(
|
||||||
{
|
{
|
||||||
auto attrs = state.buildBindings(100);
|
auto attrs = state.buildBindings(100);
|
||||||
|
|
||||||
state.mkStorePathString(storePath, attrs.alloc(state.sOutPath));
|
state.mkStorePathString(storePath, attrs.alloc(state.s.outPath));
|
||||||
|
|
||||||
// FIXME: support arbitrary input attributes.
|
// FIXME: support arbitrary input attributes.
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ static void fetchTree(
|
||||||
|
|
||||||
fetchers::Attrs attrs;
|
fetchers::Attrs attrs;
|
||||||
|
|
||||||
if (auto aType = args[0]->attrs()->get(state.sType)) {
|
if (auto aType = args[0]->attrs()->get(state.s.type)) {
|
||||||
if (type)
|
if (type)
|
||||||
state.error<EvalError>("unexpected argument 'type'").atPos(pos).debugThrow();
|
state.error<EvalError>("unexpected argument 'type'").atPos(pos).debugThrow();
|
||||||
type = state.forceStringNoCtx(
|
type = state.forceStringNoCtx(
|
||||||
|
|
@ -106,7 +106,7 @@ static void fetchTree(
|
||||||
attrs.emplace("type", type.value());
|
attrs.emplace("type", type.value());
|
||||||
|
|
||||||
for (auto & attr : *args[0]->attrs()) {
|
for (auto & attr : *args[0]->attrs()) {
|
||||||
if (attr.name == state.sType)
|
if (attr.name == state.s.type)
|
||||||
continue;
|
continue;
|
||||||
state.forceValue(*attr.value, attr.pos);
|
state.forceValue(*attr.value, attr.pos);
|
||||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ private:
|
||||||
void printDerivation(Value & v)
|
void printDerivation(Value & v)
|
||||||
{
|
{
|
||||||
std::optional<StorePath> storePath;
|
std::optional<StorePath> storePath;
|
||||||
if (auto i = v.attrs()->get(state.sDrvPath)) {
|
if (auto i = v.attrs()->get(state.s.drvPath)) {
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
storePath =
|
storePath =
|
||||||
state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation");
|
state.coerceToStorePath(i->pos, *i->value, context, "while evaluating the drvPath of a derivation");
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ json printValueAsJSON(
|
||||||
out = *maybeString;
|
out = *maybeString;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (auto i = v.attrs()->get(state.sOutPath))
|
if (auto i = v.attrs()->get(state.s.outPath))
|
||||||
return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore);
|
return printValueAsJSON(state, strict, *i->value, i->pos, context, copyToStore);
|
||||||
else {
|
else {
|
||||||
out = json::object();
|
out = json::object();
|
||||||
|
|
|
||||||
|
|
@ -98,14 +98,14 @@ static void printValueAsXML(
|
||||||
XMLAttrs xmlAttrs;
|
XMLAttrs xmlAttrs;
|
||||||
|
|
||||||
Path drvPath;
|
Path drvPath;
|
||||||
if (auto a = v.attrs()->get(state.sDrvPath)) {
|
if (auto a = v.attrs()->get(state.s.drvPath)) {
|
||||||
if (strict)
|
if (strict)
|
||||||
state.forceValue(*a->value, a->pos);
|
state.forceValue(*a->value, a->pos);
|
||||||
if (a->value->type() == nString)
|
if (a->value->type() == nString)
|
||||||
xmlAttrs["drvPath"] = drvPath = a->value->c_str();
|
xmlAttrs["drvPath"] = drvPath = a->value->c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto a = v.attrs()->get(state.sOutPath)) {
|
if (auto a = v.attrs()->get(state.s.outPath)) {
|
||||||
if (strict)
|
if (strict)
|
||||||
state.forceValue(*a->value, a->pos);
|
state.forceValue(*a->value, a->pos);
|
||||||
if (a->value->type() == nString)
|
if (a->value->type() == nString)
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ static Flake readFlake(
|
||||||
.path = flakePath,
|
.path = flakePath,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (auto description = vInfo.attrs()->get(state.sDescription)) {
|
if (auto description = vInfo.attrs()->get(state.s.description)) {
|
||||||
expectType(state, nString, *description->value, description->pos);
|
expectType(state, nString, *description->value, description->pos);
|
||||||
flake.description = description->value->c_str();
|
flake.description = description->value->c_str();
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +253,7 @@ static Flake readFlake(
|
||||||
|
|
||||||
if (outputs->value->isLambda() && outputs->value->lambda().fun->hasFormals()) {
|
if (outputs->value->isLambda() && outputs->value->lambda().fun->hasFormals()) {
|
||||||
for (auto & formal : outputs->value->lambda().fun->formals->formals) {
|
for (auto & formal : outputs->value->lambda().fun->formals->formals) {
|
||||||
if (formal.name != state.sSelf)
|
if (formal.name != state.s.self)
|
||||||
flake.inputs.emplace(
|
flake.inputs.emplace(
|
||||||
state.symbols[formal.name],
|
state.symbols[formal.name],
|
||||||
FlakeInput{.ref = parseFlakeRef(state.fetchSettings, std::string(state.symbols[formal.name]))});
|
FlakeInput{.ref = parseFlakeRef(state.fetchSettings, std::string(state.symbols[formal.name]))});
|
||||||
|
|
@ -305,7 +305,8 @@ static Flake readFlake(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto & attr : *vInfo.attrs()) {
|
for (auto & attr : *vInfo.attrs()) {
|
||||||
if (attr.name != state.sDescription && attr.name != sInputs && attr.name != sOutputs && attr.name != sNixConfig)
|
if (attr.name != state.s.description && attr.name != sInputs && attr.name != sOutputs
|
||||||
|
&& attr.name != sNixConfig)
|
||||||
throw Error(
|
throw Error(
|
||||||
"flake '%s' has an unsupported attribute '%s', at %s",
|
"flake '%s' has an unsupported attribute '%s', at %s",
|
||||||
resolvedRef,
|
resolvedRef,
|
||||||
|
|
|
||||||
|
|
@ -103,11 +103,11 @@ UnresolvedApp InstallableValue::toApp(EvalState & state)
|
||||||
|
|
||||||
else if (type == "derivation") {
|
else if (type == "derivation") {
|
||||||
auto drvPath = cursor->forceDerivation();
|
auto drvPath = cursor->forceDerivation();
|
||||||
auto outPath = cursor->getAttr(state.sOutPath)->getString();
|
auto outPath = cursor->getAttr(state.s.outPath)->getString();
|
||||||
auto outputName = cursor->getAttr(state.sOutputName)->getString();
|
auto outputName = cursor->getAttr(state.s.outputName)->getString();
|
||||||
auto name = cursor->getAttr(state.sName)->getString();
|
auto name = cursor->getAttr(state.s.name)->getString();
|
||||||
auto aPname = cursor->maybeGetAttr("pname");
|
auto aPname = cursor->maybeGetAttr("pname");
|
||||||
auto aMeta = cursor->maybeGetAttr(state.sMeta);
|
auto aMeta = cursor->maybeGetAttr(state.s.meta);
|
||||||
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
auto aMainProgram = aMeta ? aMeta->maybeGetAttr("mainProgram") : nullptr;
|
||||||
auto mainProgram = aMainProgram ? aMainProgram->getString() : aPname ? aPname->getString() : DrvName(name).name;
|
auto mainProgram = aMainProgram ? aMainProgram->getString() : aPname ? aPname->getString() : DrvName(name).name;
|
||||||
auto program = outPath + "/bin/" + mainProgram;
|
auto program = outPath + "/bin/" + mainProgram;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ struct CmdBundle : InstallableValueCommand
|
||||||
if (!evalState->isDerivation(*vRes))
|
if (!evalState->isDerivation(*vRes))
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
||||||
auto attr1 = vRes->attrs()->get(evalState->sDrvPath);
|
auto attr1 = vRes->attrs()->get(evalState->s.drvPath);
|
||||||
if (!attr1)
|
if (!attr1)
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ struct CmdBundle : InstallableValueCommand
|
||||||
|
|
||||||
drvPath.requireDerivation();
|
drvPath.requireDerivation();
|
||||||
|
|
||||||
auto attr2 = vRes->attrs()->get(evalState->sOutPath);
|
auto attr2 = vRes->attrs()->get(evalState->s.outPath);
|
||||||
if (!attr2)
|
if (!attr2)
|
||||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ struct CmdBundle : InstallableValueCommand
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!outLink) {
|
if (!outLink) {
|
||||||
auto * attr = vRes->attrs()->get(evalState->sName);
|
auto * attr = vRes->attrs()->get(evalState->s.name);
|
||||||
if (!attr)
|
if (!attr)
|
||||||
throw Error("attribute 'name' missing");
|
throw Error("attribute 'name' missing");
|
||||||
outLink = evalState->forceStringNoCtx(*attr->value, attr->pos, "");
|
outLink = evalState->forceStringNoCtx(*attr->value, attr->pos, "");
|
||||||
|
|
|
||||||
|
|
@ -1232,12 +1232,12 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
};
|
};
|
||||||
|
|
||||||
auto showDerivation = [&]() {
|
auto showDerivation = [&]() {
|
||||||
auto name = visitor.getAttr(state->sName)->getString();
|
auto name = visitor.getAttr(state->s.name)->getString();
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) {
|
if (auto aMeta = visitor.maybeGetAttr(state->s.meta)) {
|
||||||
if (auto aDescription = aMeta->maybeGetAttr(state->sDescription))
|
if (auto aDescription = aMeta->maybeGetAttr(state->s.description))
|
||||||
description = aDescription->getString();
|
description = aDescription->getString();
|
||||||
}
|
}
|
||||||
j.emplace("type", "derivation");
|
j.emplace("type", "derivation");
|
||||||
|
|
@ -1365,8 +1365,8 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
|| (attrPath.size() == 3 && attrPathS[0] == "apps")) {
|
|| (attrPath.size() == 3 && attrPathS[0] == "apps")) {
|
||||||
auto aType = visitor.maybeGetAttr("type");
|
auto aType = visitor.maybeGetAttr("type");
|
||||||
std::optional<std::string> description;
|
std::optional<std::string> description;
|
||||||
if (auto aMeta = visitor.maybeGetAttr(state->sMeta)) {
|
if (auto aMeta = visitor.maybeGetAttr(state->s.meta)) {
|
||||||
if (auto aDescription = aMeta->maybeGetAttr(state->sDescription))
|
if (auto aDescription = aMeta->maybeGetAttr(state->s.description))
|
||||||
description = aDescription->getString();
|
description = aDescription->getString();
|
||||||
}
|
}
|
||||||
if (!aType || aType->getString() != "app")
|
if (!aType || aType->getString() != "app")
|
||||||
|
|
|
||||||
|
|
@ -56,21 +56,21 @@ bool createUserEnv(
|
||||||
|
|
||||||
auto attrs = state.buildBindings(7 + outputs.size());
|
auto attrs = state.buildBindings(7 + outputs.size());
|
||||||
|
|
||||||
attrs.alloc(state.sType).mkString("derivation");
|
attrs.alloc(state.s.type).mkString("derivation");
|
||||||
attrs.alloc(state.sName).mkString(i.queryName());
|
attrs.alloc(state.s.name).mkString(i.queryName());
|
||||||
auto system = i.querySystem();
|
auto system = i.querySystem();
|
||||||
if (!system.empty())
|
if (!system.empty())
|
||||||
attrs.alloc(state.sSystem).mkString(system);
|
attrs.alloc(state.s.system).mkString(system);
|
||||||
attrs.alloc(state.sOutPath).mkString(state.store->printStorePath(i.queryOutPath()));
|
attrs.alloc(state.s.outPath).mkString(state.store->printStorePath(i.queryOutPath()));
|
||||||
if (drvPath)
|
if (drvPath)
|
||||||
attrs.alloc(state.sDrvPath).mkString(state.store->printStorePath(*drvPath));
|
attrs.alloc(state.s.drvPath).mkString(state.store->printStorePath(*drvPath));
|
||||||
|
|
||||||
// Copy each output meant for installation.
|
// Copy each output meant for installation.
|
||||||
auto outputsList = state.buildList(outputs.size());
|
auto outputsList = state.buildList(outputs.size());
|
||||||
for (const auto & [m, j] : enumerate(outputs)) {
|
for (const auto & [m, j] : enumerate(outputs)) {
|
||||||
(outputsList[m] = state.allocValue())->mkString(j.first);
|
(outputsList[m] = state.allocValue())->mkString(j.first);
|
||||||
auto outputAttrs = state.buildBindings(2);
|
auto outputAttrs = state.buildBindings(2);
|
||||||
outputAttrs.alloc(state.sOutPath).mkString(state.store->printStorePath(*j.second));
|
outputAttrs.alloc(state.s.outPath).mkString(state.store->printStorePath(*j.second));
|
||||||
attrs.alloc(j.first).mkAttrs(outputAttrs);
|
attrs.alloc(j.first).mkAttrs(outputAttrs);
|
||||||
|
|
||||||
/* This is only necessary when installing store paths, e.g.,
|
/* This is only necessary when installing store paths, e.g.,
|
||||||
|
|
@ -80,7 +80,7 @@ bool createUserEnv(
|
||||||
|
|
||||||
references.insert(*j.second);
|
references.insert(*j.second);
|
||||||
}
|
}
|
||||||
attrs.alloc(state.sOutputs).mkList(outputsList);
|
attrs.alloc(state.s.outputs).mkList(outputsList);
|
||||||
|
|
||||||
// Copy the meta attributes.
|
// Copy the meta attributes.
|
||||||
auto meta = state.buildBindings(metaNames.size());
|
auto meta = state.buildBindings(metaNames.size());
|
||||||
|
|
@ -91,7 +91,7 @@ bool createUserEnv(
|
||||||
meta.insert(state.symbols.create(j), v);
|
meta.insert(state.symbols.create(j), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
attrs.alloc(state.sMeta).mkAttrs(meta);
|
attrs.alloc(state.s.meta).mkAttrs(meta);
|
||||||
|
|
||||||
(list[n] = state.allocValue())->mkAttrs(attrs);
|
(list[n] = state.allocValue())->mkAttrs(attrs);
|
||||||
|
|
||||||
|
|
@ -141,10 +141,10 @@ bool createUserEnv(
|
||||||
debug("evaluating user environment builder");
|
debug("evaluating user environment builder");
|
||||||
state.forceValue(topLevel, topLevel.determinePos(noPos));
|
state.forceValue(topLevel, topLevel.determinePos(noPos));
|
||||||
NixStringContext context;
|
NixStringContext context;
|
||||||
auto & aDrvPath(*topLevel.attrs()->find(state.sDrvPath));
|
auto & aDrvPath(*topLevel.attrs()->find(state.s.drvPath));
|
||||||
auto topLevelDrv = state.coerceToStorePath(aDrvPath.pos, *aDrvPath.value, context, "");
|
auto topLevelDrv = state.coerceToStorePath(aDrvPath.pos, *aDrvPath.value, context, "");
|
||||||
topLevelDrv.requireDerivation();
|
topLevelDrv.requireDerivation();
|
||||||
auto & aOutPath(*topLevel.attrs()->find(state.sOutPath));
|
auto & aOutPath(*topLevel.attrs()->find(state.s.outPath));
|
||||||
auto topLevelOut = state.coerceToStorePath(aOutPath.pos, *aOutPath.value, context, "");
|
auto topLevelOut = state.coerceToStorePath(aOutPath.pos, *aOutPath.value, context, "");
|
||||||
|
|
||||||
/* Realise the resulting store expression. */
|
/* Realise the resulting store expression. */
|
||||||
|
|
|
||||||
|
|
@ -108,10 +108,10 @@ struct CmdSearch : InstallableValueCommand, MixJSON
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cursor.isDerivation()) {
|
if (cursor.isDerivation()) {
|
||||||
DrvName name(cursor.getAttr(state->sName)->getString());
|
DrvName name(cursor.getAttr(state->s.name)->getString());
|
||||||
|
|
||||||
auto aMeta = cursor.maybeGetAttr(state->sMeta);
|
auto aMeta = cursor.maybeGetAttr(state->s.meta);
|
||||||
auto aDescription = aMeta ? aMeta->maybeGetAttr(state->sDescription) : nullptr;
|
auto aDescription = aMeta ? aMeta->maybeGetAttr(state->s.description) : nullptr;
|
||||||
auto description = aDescription ? aDescription->getString() : "";
|
auto description = aDescription ? aDescription->getString() : "";
|
||||||
std::replace(description.begin(), description.end(), '\n', ' ');
|
std::replace(description.begin(), description.end(), '\n', ' ');
|
||||||
auto attrPath2 = concatStringsSep(".", attrPathS);
|
auto attrPath2 = concatStringsSep(".", attrPathS);
|
||||||
|
|
@ -176,7 +176,7 @@ struct CmdSearch : InstallableValueCommand, MixJSON
|
||||||
recurse();
|
recurse();
|
||||||
|
|
||||||
else if (attrPathS[0] == "legacyPackages" && attrPath.size() > 2) {
|
else if (attrPathS[0] == "legacyPackages" && attrPath.size() > 2) {
|
||||||
auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
|
auto attr = cursor.maybeGetAttr(state->s.recurseForDerivations);
|
||||||
if (attr && attr->getBool())
|
if (attr && attr->getBool())
|
||||||
recurse();
|
recurse();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue