libexpr: "hide" Value union members
on its own this is not very useful, but having accessors for every value kind is a prerequisite for doing smart things with Value than the union. the net effect for now is only to add a few parentheses across the tree. Change-Id: I88688ac09eb08495dad1eb221034ca540f094950
This commit is contained in:
@@ -272,7 +272,7 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a
|
||||
}
|
||||
bool add = false;
|
||||
if (v.type() == nFunction) {
|
||||
if (auto pattern = dynamic_cast<AttrsPattern *>(v.lambda.fun->pattern.get())) {
|
||||
if (auto pattern = dynamic_cast<AttrsPattern *>(v.lambda().fun->pattern.get())) {
|
||||
for (auto & i : pattern->formals) {
|
||||
if (evaluator->symbols[i.name] == "inNixShell") {
|
||||
add = true;
|
||||
|
||||
@@ -1275,15 +1275,15 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||
xml.writeEmptyElement("meta", attrs2);
|
||||
} else if (v->type() == nInt) {
|
||||
attrs2["type"] = "int";
|
||||
attrs2["value"] = fmt("%1%", v->integer);
|
||||
attrs2["value"] = fmt("%1%", v->integer());
|
||||
xml.writeEmptyElement("meta", attrs2);
|
||||
} else if (v->type() == nFloat) {
|
||||
attrs2["type"] = "float";
|
||||
attrs2["value"] = fmt("%1%", v->fpoint);
|
||||
attrs2["value"] = fmt("%1%", v->fpoint());
|
||||
xml.writeEmptyElement("meta", attrs2);
|
||||
} else if (v->type() == nBool) {
|
||||
attrs2["type"] = "bool";
|
||||
attrs2["value"] = v->boolean ? "true" : "false";
|
||||
attrs2["value"] = v->boolean() ? "true" : "false";
|
||||
xml.writeEmptyElement("meta", attrs2);
|
||||
} else if (v->type() == nList) {
|
||||
attrs2["type"] = "strings";
|
||||
@@ -1297,7 +1297,7 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
|
||||
} else if (v->type() == nAttrs) {
|
||||
attrs2["type"] = "strings";
|
||||
XMLOpenElement m(xml, "meta", attrs2);
|
||||
Bindings & attrs = *v->attrs;
|
||||
Bindings & attrs = *v->attrs();
|
||||
for (auto &i : attrs) {
|
||||
const Attr & a(*attrs.get(i.name));
|
||||
if(a.value->type() != nString) continue;
|
||||
|
||||
@@ -114,9 +114,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.s.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.s.outPath));
|
||||
auto topLevelOut = state.coerceToStorePath(aOutPath.pos, *aOutPath.value, context, "");
|
||||
|
||||
/* Realise the resulting store expression. */
|
||||
|
||||
@@ -242,7 +242,7 @@ void SourceExprCommand::completeInstallable(EvalState & state, AddCompletions &
|
||||
state.autoCallFunction(*autoArgs, v1, v2, pos);
|
||||
|
||||
if (v2.type() == nAttrs) {
|
||||
for (auto & i : *v2.attrs) {
|
||||
for (auto & i : *v2.attrs()) {
|
||||
std::string name{evaluator->symbols[i.name]};
|
||||
if (name.find(searchWord) == 0) {
|
||||
if (prefix_ == "")
|
||||
@@ -417,7 +417,7 @@ ref<eval_cache::EvalCache> openEvalCache(
|
||||
|
||||
state.forceAttrs(*vFlake, noPos, "while parsing cached flake data");
|
||||
|
||||
auto aOutputs = vFlake->attrs->get(state.ctx.symbols.create("outputs"));
|
||||
auto aOutputs = vFlake->attrs()->get(state.ctx.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
|
||||
return aOutputs->value;
|
||||
|
||||
+6
-6
@@ -450,7 +450,7 @@ StringSet NixRepl::completePrefix(const std::string &prefix)
|
||||
e.eval(state, *env, v);
|
||||
state.forceAttrs(v, noPos, "while evaluating an attrset for the purpose of completion (this error should not be displayed; file an issue?)");
|
||||
|
||||
for (auto & i : *v.attrs) {
|
||||
for (auto & i : *v.attrs()) {
|
||||
std::ostringstream output;
|
||||
printAttributeName(output, evaluator.symbols[i.name]);
|
||||
std::string name = output.str();
|
||||
@@ -653,7 +653,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
auto path = state.coerceToPath(noPos, v, context, "while evaluating the filename to edit");
|
||||
return {path, 0};
|
||||
} else if (v.isLambda()) {
|
||||
auto pos = evaluator.positions[v.lambda.fun->pos];
|
||||
auto pos = evaluator.positions[v.lambda().fun->pos];
|
||||
if (auto path = std::get_if<CheckedSourcePath>(&pos.origin))
|
||||
return {*path, pos.line};
|
||||
else
|
||||
@@ -822,7 +822,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
|
||||
|
||||
logger->cout(trim(renderMarkdownToTerminal(markdown)));
|
||||
} else if (v.isLambda()) {
|
||||
auto pos = evaluator.positions[v.lambda.fun->pos];
|
||||
auto pos = evaluator.positions[v.lambda().fun->pos];
|
||||
if (auto path = std::get_if<CheckedSourcePath>(&pos.origin)) {
|
||||
// Path and position have now been obtained, feed to nix-doc library to get data.
|
||||
auto docComment = lambdaDocsForPos(*path, pos);
|
||||
@@ -1027,13 +1027,13 @@ Value * NixRepl::replOverlays()
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
if (auto attrs = dynamic_cast<AttrsPattern *>(replInit->lambda.fun->pattern.get()); attrs && !attrs->ellipsis) {
|
||||
if (auto attrs = dynamic_cast<AttrsPattern *>(replInit->lambda().fun->pattern.get()); attrs && !attrs->ellipsis) {
|
||||
evaluator.errors.make<TypeError>(
|
||||
"Expected first argument of %1% to have %2% to allow future versions of Lix to add additional attributes to the argument",
|
||||
"repl-overlays",
|
||||
"..."
|
||||
)
|
||||
.atPos(replInit->lambda.fun->pos)
|
||||
.atPos(replInit->lambda().fun->pos)
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
@@ -1090,7 +1090,7 @@ void NixRepl::addAttrsToScope(Value & attrs)
|
||||
{
|
||||
state.forceAttrs(attrs, noPos, "while evaluating an attribute set to be merged in the global scope");
|
||||
addToScope(
|
||||
*attrs.attrs, [](const Attr & a) { return a.name; }, [](const Attr & a) { return a.value; }
|
||||
*attrs.attrs(), [](const Attr & a) { return a.name; }, [](const Attr & a) { return a.value; }
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,10 +111,10 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
auto a = v->attrs->get(state.ctx.symbols.create(attr));
|
||||
auto a = v->attrs()->get(state.ctx.symbols.create(attr));
|
||||
if (!a) {
|
||||
std::set<std::string> attrNames;
|
||||
for (auto & attr : *v->attrs)
|
||||
for (auto & attr : *v->attrs())
|
||||
attrNames.emplace(state.ctx.symbols[attr.name]);
|
||||
|
||||
auto suggestions = Suggestions::bestMatches(attrNames, attr);
|
||||
|
||||
@@ -383,7 +383,7 @@ Value & AttrCursor::getValue(EvalState & state)
|
||||
if (parent) {
|
||||
auto & vParent = parent->first->getValue(state);
|
||||
state.forceAttrs(vParent, noPos, "while searching for an attribute");
|
||||
auto attr = vParent.attrs->get(state.ctx.symbols.create(parent->second));
|
||||
auto attr = vParent.attrs()->get(state.ctx.symbols.create(parent->second));
|
||||
if (!attr)
|
||||
throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr(state));
|
||||
_value = allocRootValue(attr->value);
|
||||
@@ -438,16 +438,16 @@ Value & AttrCursor::forceValue(EvalState & state)
|
||||
if (root->db && (!cachedValue || std::get_if<placeholder_t>(&cachedValue->second))) {
|
||||
if (v.type() == nString)
|
||||
cachedValue = {
|
||||
root->db->setString(getKey(), v.str(), v.string.context), string_t{v.str(), {}}
|
||||
root->db->setString(getKey(), v.str(), v.string().context), string_t{v.str(), {}}
|
||||
};
|
||||
else if (v.type() == nPath) {
|
||||
auto path = v.path().canonical().abs();
|
||||
cachedValue = {root->db->setString(getKey(), path), string_t{path, {}}};
|
||||
}
|
||||
else if (v.type() == nBool)
|
||||
cachedValue = {root->db->setBool(getKey(), v.boolean), v.boolean};
|
||||
cachedValue = {root->db->setBool(getKey(), v.boolean()), v.boolean()};
|
||||
else if (v.type() == nInt)
|
||||
cachedValue = {root->db->setInt(getKey(), v.integer.value), int_t{v.integer}};
|
||||
cachedValue = {root->db->setInt(getKey(), v.integer().value), int_t{v.integer()}};
|
||||
else if (v.type() == nAttrs)
|
||||
; // FIXME: do something?
|
||||
else
|
||||
@@ -500,7 +500,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(EvalState & state, const st
|
||||
return nullptr;
|
||||
//errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
|
||||
auto attr = v.attrs->get(state.ctx.symbols.create(name));
|
||||
auto attr = v.attrs()->get(state.ctx.symbols.create(name));
|
||||
|
||||
if (!attr) {
|
||||
if (root->db) {
|
||||
@@ -633,7 +633,7 @@ bool AttrCursor::getBool(EvalState & state)
|
||||
if (v.type() != nBool)
|
||||
state.ctx.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
|
||||
|
||||
return v.boolean;
|
||||
return v.boolean();
|
||||
}
|
||||
|
||||
NixInt AttrCursor::getInt(EvalState & state)
|
||||
@@ -655,7 +655,7 @@ NixInt AttrCursor::getInt(EvalState & state)
|
||||
if (v.type() != nInt)
|
||||
state.ctx.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
|
||||
|
||||
return v.integer;
|
||||
return v.integer();
|
||||
}
|
||||
|
||||
std::vector<std::string> AttrCursor::getListOfStrings(EvalState & state)
|
||||
@@ -711,7 +711,7 @@ std::vector<std::string> AttrCursor::getAttrs(EvalState & state)
|
||||
state.ctx.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
|
||||
|
||||
fullattr_t attrs;
|
||||
for (auto & attr : *getValue(state).attrs)
|
||||
for (auto & attr : *getValue(state).attrs())
|
||||
attrs.p.emplace_back(state.ctx.symbols[attr.name]);
|
||||
std::sort(attrs.p.begin(), attrs.p.end());
|
||||
|
||||
|
||||
@@ -69,8 +69,8 @@ Env & EvalMemory::allocEnv(size_t size)
|
||||
void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
{
|
||||
if (v.isThunk()) {
|
||||
Env * env = v.thunk.env;
|
||||
Expr & expr = *v.thunk.expr;
|
||||
Env * env = v.thunk().env;
|
||||
Expr & expr = *v.thunk().expr;
|
||||
try {
|
||||
v.mkBlackhole();
|
||||
expr.eval(*this, *env, v);
|
||||
@@ -81,7 +81,7 @@ void EvalState::forceValue(Value & v, const PosIdx pos)
|
||||
}
|
||||
}
|
||||
else if (v.isApp())
|
||||
callFunction(*v.app.left, *v.app.right, v, pos);
|
||||
callFunction(*v.app().left, *v.app().right, v, pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+105
-93
@@ -25,6 +25,7 @@
|
||||
#include "lix/libutil/exit.hh"
|
||||
#include "lix/libutil/json.hh"
|
||||
#include "symbol-table.hh"
|
||||
#include "value.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -74,7 +75,7 @@ std::string printValue(EvalState & state, Value & v)
|
||||
const Value * getPrimOp(const Value &v) {
|
||||
const Value * primOp = &v;
|
||||
while (primOp->isPrimOpApp()) {
|
||||
primOp = primOp->primOpApp.left;
|
||||
primOp = primOp->primOpApp().left;
|
||||
}
|
||||
assert(primOp->isPrimOp());
|
||||
return primOp;
|
||||
@@ -106,12 +107,12 @@ std::string showType(const Value & v)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||
switch (v.internalType) {
|
||||
case tString: return v.string.context ? "a string with context" : "a string";
|
||||
case tString: return v.string().context ? "a string with context" : "a string";
|
||||
case tPrimOp:
|
||||
return fmt("the built-in function '%s'", std::string(v.primOp->name));
|
||||
return fmt("the built-in function '%s'", std::string(v.primOp()->name));
|
||||
case tPrimOpApp:
|
||||
return fmt("the partially applied built-in function '%s'", std::string(getPrimOp(v)->primOp->name));
|
||||
case tExternal: return v.external->showType();
|
||||
return fmt("the partially applied built-in function '%s'", std::string(getPrimOp(v)->primOp()->name));
|
||||
case tExternal: return v.external()->showType();
|
||||
case tThunk: return v.isBlackhole() ? "a black hole" : "a thunk";
|
||||
case tApp: return "a function application";
|
||||
default:
|
||||
@@ -550,7 +551,7 @@ void EvalBuiltins::addConstant(const std::string & name, Value * v, Constant inf
|
||||
/* Install value the base environment. */
|
||||
staticEnv->vars.insert_or_assign(symbols.create(name), baseEnvDispl);
|
||||
env.values[baseEnvDispl++] = v;
|
||||
env.values[0]->attrs->push_back(Attr(symbols.create(name2), v));
|
||||
env.values[0]->attrs()->push_back(Attr(symbols.create(name2), v));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,14 +586,14 @@ Value * EvalBuiltins::addPrimOp(PrimOp && primOp)
|
||||
v->mkPrimOp(new PrimOp(primOp));
|
||||
staticEnv->vars.insert_or_assign(auto(envName), baseEnvDispl);
|
||||
env.values[baseEnvDispl++] = v;
|
||||
env.values[0]->attrs->push_back(Attr(symbols.create(primOp.name), v));
|
||||
env.values[0]->attrs()->push_back(Attr(symbols.create(primOp.name), v));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
Value & EvalBuiltins::get(const std::string & name)
|
||||
{
|
||||
return *env.values[0]->attrs->get(symbols.create(name))->value;
|
||||
return *env.values[0]->attrs()->get(symbols.create(name))->value;
|
||||
}
|
||||
|
||||
|
||||
@@ -600,12 +601,12 @@ std::optional<EvalBuiltins::Doc> EvalBuiltins::getDoc(Value & v)
|
||||
{
|
||||
if (v.isPrimOp()) {
|
||||
auto v2 = &v;
|
||||
if (auto * doc = v2->primOp->doc)
|
||||
if (auto * doc = v2->primOp()->doc)
|
||||
return Doc {
|
||||
.pos = {},
|
||||
.name = v2->primOp->name,
|
||||
.arity = v2->primOp->arity,
|
||||
.args = v2->primOp->args,
|
||||
.name = v2->primOp()->name,
|
||||
.arity = v2->primOp()->arity,
|
||||
.args = v2->primOp()->args,
|
||||
.doc = doc,
|
||||
};
|
||||
}
|
||||
@@ -637,7 +638,7 @@ void printWithBindings(const SymbolTable & st, const Env & env)
|
||||
{
|
||||
if (env.values[0]->type() == nAttrs) {
|
||||
std::set<std::string_view> bindings;
|
||||
for (const auto & attr : *env.values[0]->attrs)
|
||||
for (const auto & attr : *env.values[0]->attrs())
|
||||
bindings.emplace(st[attr.name]);
|
||||
|
||||
std::cout << "with: ";
|
||||
@@ -694,8 +695,8 @@ void mapStaticEnvBindings(const SymbolTable & st, const StaticEnv & se, const En
|
||||
|
||||
if (se.isWith && env.values[0]->type() == nAttrs) {
|
||||
// add 'with' bindings.
|
||||
Bindings::iterator j = env.values[0]->attrs->begin();
|
||||
while (j != env.values[0]->attrs->end()) {
|
||||
Bindings::iterator j = env.values[0]->attrs()->begin();
|
||||
while (j != env.values[0]->attrs()->end()) {
|
||||
vm[std::string(st[j->name])] = j->value;
|
||||
++j;
|
||||
}
|
||||
@@ -833,7 +834,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
||||
auto * fromWith = var.fromWith;
|
||||
while (1) {
|
||||
forceAttrs(*env->values[0], fromWith->pos, "while evaluating the first subexpression of a with expression");
|
||||
auto j = env->values[0]->attrs->get(var.name);
|
||||
auto j = env->values[0]->attrs()->get(var.name);
|
||||
if (j) {
|
||||
if (ctx.stats.countCalls) ctx.stats.attrSelects[j->pos]++;
|
||||
return j->value;
|
||||
@@ -850,7 +851,7 @@ Value EvalMemory::newList(size_t size)
|
||||
Value v;
|
||||
v.mkList(size);
|
||||
if (size > 2)
|
||||
v.bigList.elems = gcAllocType<Value *>(size);
|
||||
v._bigList.elems = gcAllocType<Value *>(size);
|
||||
stats.nrListElems += size;
|
||||
return v;
|
||||
}
|
||||
@@ -1034,7 +1035,7 @@ inline bool EvalState::evalBool(Env & env, Expr & e)
|
||||
Value v;
|
||||
e.eval(*this, env, v);
|
||||
checkType(nBool, "Boolean");
|
||||
return v.boolean;
|
||||
return v.boolean();
|
||||
}
|
||||
|
||||
|
||||
@@ -1105,7 +1106,7 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
|
||||
} else
|
||||
vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv));
|
||||
env2.values[displ++] = vAttr;
|
||||
v.attrs->push_back(Attr(i.first, vAttr, i.second.pos));
|
||||
v.attrs()->push_back(Attr(i.first, vAttr, i.second.pos));
|
||||
}
|
||||
|
||||
/* If the rec contains an attribute called `__overrides', then
|
||||
@@ -1117,12 +1118,12 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
|
||||
been substituted into the bodies of the other attributes.
|
||||
Hence we need __overrides.) */
|
||||
if (hasOverrides) {
|
||||
Value * vOverrides = (*v.attrs)[overrides->second.displ].value;
|
||||
Value * vOverrides = (*v.attrs())[overrides->second.displ].value;
|
||||
state.forceAttrs(*vOverrides, noPos, "while evaluating the `__overrides` attribute");
|
||||
Bindings * newBnds = state.ctx.mem.allocBindings(capacity + vOverrides->attrs->size());
|
||||
for (auto & i : *v.attrs)
|
||||
Bindings * newBnds = state.ctx.mem.allocBindings(capacity + vOverrides->attrs()->size());
|
||||
for (auto & i : *v.attrs())
|
||||
newBnds->push_back(i);
|
||||
for (auto & i : *vOverrides->attrs) {
|
||||
for (auto & i : *vOverrides->attrs()) {
|
||||
ExprAttrs::AttrDefs::iterator j = attrs.find(i.name);
|
||||
if (j != attrs.end()) {
|
||||
(*newBnds)[j->second.displ] = i;
|
||||
@@ -1131,14 +1132,14 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
|
||||
newBnds->push_back(i);
|
||||
}
|
||||
newBnds->sort();
|
||||
v.attrs = newBnds;
|
||||
v.mkAttrs(newBnds);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env) : nullptr;
|
||||
for (auto & i : attrs) {
|
||||
v.attrs->push_back(Attr(
|
||||
v.attrs()->push_back(Attr(
|
||||
i.first,
|
||||
i.second.e->maybeThunk(state, *i.second.chooseByKind(&env, &env, inheritEnv)),
|
||||
i.second.pos));
|
||||
@@ -1154,7 +1155,7 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
|
||||
continue;
|
||||
state.forceStringNoCtx(nameVal, i.pos, "while evaluating the name of a dynamic attribute");
|
||||
auto nameSym = state.ctx.symbols.create(nameVal.str());
|
||||
auto j = v.attrs->get(nameSym);
|
||||
auto j = v.attrs()->get(nameSym);
|
||||
if (j) {
|
||||
state.ctx.errors
|
||||
.make<EvalError>(
|
||||
@@ -1169,11 +1170,11 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
i.valueExpr->setName(nameSym);
|
||||
/* Keep sorted order so find can catch duplicates */
|
||||
v.attrs->push_back(Attr(nameSym, i.valueExpr->maybeThunk(state, *dynamicEnv), i.pos));
|
||||
v.attrs->sort(); // FIXME: inefficient
|
||||
v.attrs()->push_back(Attr(nameSym, i.valueExpr->maybeThunk(state, *dynamicEnv), i.pos));
|
||||
v.attrs()->sort(); // FIXME: inefficient
|
||||
}
|
||||
|
||||
v.attrs->pos = pos;
|
||||
v.attrs()->pos = pos;
|
||||
}
|
||||
|
||||
|
||||
@@ -1324,7 +1325,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
// Now that we know this is actually an attrset, try to find an attr
|
||||
// with the selected name.
|
||||
auto attrIt = vCurrent->attrs->get(name);
|
||||
auto attrIt = vCurrent->attrs()->get(name);
|
||||
if (!attrIt) {
|
||||
|
||||
// If we have an `or` provided default, then we'll use that.
|
||||
@@ -1335,7 +1336,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
// Otherwise, missing attr error.
|
||||
std::set<std::string> allAttrNames;
|
||||
for (auto const & attr : *vCurrent->attrs) {
|
||||
for (auto const & attr : *vCurrent->attrs()) {
|
||||
allAttrNames.emplace(state.ctx.symbols[attr.name]);
|
||||
}
|
||||
auto suggestions = Suggestions::bestMatches(allAttrNames, state.ctx.symbols[name]);
|
||||
@@ -1379,7 +1380,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
|
||||
state.forceValue(*vAttrs, getPos());
|
||||
const Attr * j;
|
||||
auto name = getName(i, state, env);
|
||||
if (vAttrs->type() != nAttrs || (j = vAttrs->attrs->get(name)) == nullptr) {
|
||||
if (vAttrs->type() != nAttrs || (j = vAttrs->attrs()->get(name)) == nullptr) {
|
||||
v.mkBool(false);
|
||||
return;
|
||||
} else {
|
||||
@@ -1499,7 +1500,7 @@ Env & AttrsPattern::match(ExprLambda & lambda, EvalState & state, Env & up, Valu
|
||||
env2,
|
||||
displ,
|
||||
*this,
|
||||
*arg->attrs,
|
||||
*arg->attrs(),
|
||||
ctx.symbols
|
||||
);
|
||||
|
||||
@@ -1576,9 +1577,9 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
|
||||
if (vCur.isLambda()) {
|
||||
|
||||
ExprLambda & lambda(*vCur.lambda.fun);
|
||||
ExprLambda & lambda(*vCur.lambda().fun);
|
||||
|
||||
Env & env2 = lambda.pattern->match(lambda, *this, *vCur.lambda.env, args[0], pos);
|
||||
Env & env2 = lambda.pattern->match(lambda, *this, *vCur.lambda().env, args[0], pos);
|
||||
|
||||
ctx.stats.nrFunctionCalls++;
|
||||
if (ctx.stats.countCalls) ctx.stats.addCall(lambda);
|
||||
@@ -1603,7 +1604,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
|
||||
else if (vCur.isPrimOp()) {
|
||||
|
||||
size_t argsLeft = vCur.primOp->arity;
|
||||
size_t argsLeft = vCur.primOp()->arity;
|
||||
|
||||
if (nrArgs < argsLeft) {
|
||||
/* We don't have enough arguments, so create a tPrimOpApp chain. */
|
||||
@@ -1611,7 +1612,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
return;
|
||||
} else {
|
||||
/* We have all the arguments, so call the primop. */
|
||||
auto * fn = vCur.primOp;
|
||||
auto * fn = vCur.primOp();
|
||||
|
||||
ctx.stats.nrPrimOpCalls++;
|
||||
if (ctx.stats.countCalls) ctx.stats.primOpCalls[fn->name]++;
|
||||
@@ -1643,10 +1644,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
Value * primOp = &vCur;
|
||||
while (primOp->isPrimOpApp()) {
|
||||
argsDone++;
|
||||
primOp = primOp->primOpApp.left;
|
||||
primOp = primOp->primOpApp().left;
|
||||
}
|
||||
assert(primOp->isPrimOp());
|
||||
auto arity = primOp->primOp->arity;
|
||||
auto arity = primOp->primOp()->arity;
|
||||
auto argsLeft = arity - argsDone;
|
||||
|
||||
if (nrArgs < argsLeft) {
|
||||
@@ -1660,13 +1661,13 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
// max arity as of writing is 3. even 4 seems excessive though.
|
||||
SmallVector<Value *, 4> vArgs(arity);
|
||||
auto n = argsDone;
|
||||
for (Value * arg = &vCur; arg->isPrimOpApp(); arg = arg->primOpApp.left)
|
||||
vArgs[--n] = arg->primOpApp.right;
|
||||
for (Value * arg = &vCur; arg->isPrimOpApp(); arg = arg->primOpApp().left)
|
||||
vArgs[--n] = arg->primOpApp().right;
|
||||
|
||||
for (size_t i = 0; i < argsLeft; ++i)
|
||||
vArgs[argsDone + i] = args[i];
|
||||
|
||||
auto fn = primOp->primOp;
|
||||
auto fn = primOp->primOp();
|
||||
ctx.stats.nrPrimOpCalls++;
|
||||
if (ctx.stats.countCalls) ctx.stats.primOpCalls[fn->name]++;
|
||||
|
||||
@@ -1686,7 +1687,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
}
|
||||
}
|
||||
|
||||
else if (vCur.type() == nAttrs && (functor = vCur.attrs->get(ctx.s.functor))) {
|
||||
else if (vCur.type() == nAttrs && (functor = vCur.attrs()->get(ctx.s.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. */
|
||||
@@ -1747,7 +1748,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.s.functor);
|
||||
if (found) {
|
||||
Value * v = ctx.mem.allocValue();
|
||||
callFunction(*found->value, fun, *v, pos);
|
||||
@@ -1760,7 +1761,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res, PosI
|
||||
res = fun;
|
||||
return;
|
||||
}
|
||||
auto pattern = dynamic_cast<AttrsPattern *>(fun.lambda.fun->pattern.get());
|
||||
auto pattern = dynamic_cast<AttrsPattern *>(fun.lambda().fun->pattern.get());
|
||||
if (!pattern) {
|
||||
res = fun;
|
||||
return;
|
||||
@@ -1786,7 +1787,7 @@ Lix attempted to evaluate a function as a top level expression; in
|
||||
this case it must have its arguments supplied either by default
|
||||
values, or passed explicitly with '--arg' or '--argstr'. See
|
||||
https://docs.lix.systems/manual/lix/stable/language/constructs.html#functions)", ctx.symbols[i.name])
|
||||
.atPos(i.pos).withFrame(*fun.lambda.env, *fun.lambda.fun).debugThrow();
|
||||
.atPos(i.pos).withFrame(*fun.lambda().env, *fun.lambda().fun).debugThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1871,17 +1872,17 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
state.ctx.stats.nrOpUpdates++;
|
||||
|
||||
if (v1.attrs->size() == 0) { v = v2; return; }
|
||||
if (v2.attrs->size() == 0) { v = v1; return; }
|
||||
if (v1.attrs()->size() == 0) { v = v2; return; }
|
||||
if (v2.attrs()->size() == 0) { v = v1; return; }
|
||||
|
||||
auto attrs = state.ctx.buildBindings(v1.attrs->size() + v2.attrs->size());
|
||||
auto attrs = state.ctx.buildBindings(v1.attrs()->size() + v2.attrs()->size());
|
||||
|
||||
/* Merge the sets, preferring values from the second set. Make
|
||||
sure to keep the resulting vector in sorted order. */
|
||||
Bindings::iterator i = v1.attrs->begin();
|
||||
Bindings::iterator j = v2.attrs->begin();
|
||||
Bindings::iterator i = v1.attrs()->begin();
|
||||
Bindings::iterator j = v2.attrs()->begin();
|
||||
|
||||
while (i != v1.attrs->end() && j != v2.attrs->end()) {
|
||||
while (i != v1.attrs()->end() && j != v2.attrs()->end()) {
|
||||
if (i->name == j->name) {
|
||||
attrs.insert(*j);
|
||||
++i; ++j;
|
||||
@@ -1892,12 +1893,12 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||
attrs.insert(*j++);
|
||||
}
|
||||
|
||||
while (i != v1.attrs->end()) attrs.insert(*i++);
|
||||
while (j != v2.attrs->end()) attrs.insert(*j++);
|
||||
while (i != v1.attrs()->end()) attrs.insert(*i++);
|
||||
while (j != v2.attrs()->end()) attrs.insert(*j++);
|
||||
|
||||
v.mkAttrs(attrs.alreadySorted());
|
||||
|
||||
state.ctx.stats.nrOpUpdateValuesCopied += v.attrs->size();
|
||||
state.ctx.stats.nrOpUpdateValuesCopied += v.attrs()->size();
|
||||
}
|
||||
|
||||
|
||||
@@ -2003,24 +2004,27 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
if (firstType == nInt) {
|
||||
if (vTmp.type() == nInt) {
|
||||
auto newN = n + vTmp.integer;
|
||||
auto newN = n + vTmp.integer();
|
||||
if (auto checked = newN.valueChecked(); checked.has_value()) {
|
||||
n = NixInt(*checked);
|
||||
} else {
|
||||
state.ctx.errors.make<EvalError>("integer overflow in adding %1% + %2%", n, vTmp.integer).atPos(i_pos).debugThrow();
|
||||
state.ctx.errors
|
||||
.make<EvalError>("integer overflow in adding %1% + %2%", n, vTmp.integer())
|
||||
.atPos(i_pos)
|
||||
.debugThrow();
|
||||
}
|
||||
} else if (vTmp.type() == nFloat) {
|
||||
// Upgrade the type from int to float;
|
||||
firstType = nFloat;
|
||||
nf = n.value;
|
||||
nf += vTmp.fpoint;
|
||||
nf += vTmp.fpoint();
|
||||
} else
|
||||
state.ctx.errors.make<EvalError>("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
|
||||
} else if (firstType == nFloat) {
|
||||
if (vTmp.type() == nInt) {
|
||||
nf += vTmp.integer.value;
|
||||
nf += vTmp.integer().value;
|
||||
} else if (vTmp.type() == nFloat) {
|
||||
nf += vTmp.fpoint;
|
||||
nf += vTmp.fpoint();
|
||||
} else
|
||||
state.ctx.errors.make<EvalError>("cannot add %1% to a float", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
|
||||
} else {
|
||||
@@ -2104,11 +2108,11 @@ void EvalState::forceValueDeep(Value & v)
|
||||
forceValue(v, noPos);
|
||||
|
||||
if (v.type() == nAttrs) {
|
||||
for (auto & i : *v.attrs)
|
||||
for (auto & i : *v.attrs())
|
||||
try {
|
||||
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
|
||||
auto dts = ctx.debug && i.value->isThunk()
|
||||
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, ctx.positions[i.pos],
|
||||
? makeDebugTraceStacker(*this, *i.value->thunk().expr, *i.value->thunk().env, ctx.positions[i.pos],
|
||||
"while evaluating the attribute '%1%'", ctx.symbols[i.name])
|
||||
: nullptr;
|
||||
|
||||
@@ -2139,13 +2143,13 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCt
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).atPos(pos).debugThrow();
|
||||
return v.integer;
|
||||
return v.integer();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(ctx.positions[pos], errorCtx);
|
||||
throw;
|
||||
}
|
||||
|
||||
return v.integer;
|
||||
return v.integer();
|
||||
}
|
||||
|
||||
|
||||
@@ -2154,14 +2158,14 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err
|
||||
try {
|
||||
forceValue(v, pos);
|
||||
if (v.type() == nInt)
|
||||
return v.integer.value;
|
||||
return v.integer().value;
|
||||
else if (v.type() != nFloat)
|
||||
ctx.errors.make<TypeError>(
|
||||
"expected a float but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).atPos(pos).debugThrow();
|
||||
return v.fpoint;
|
||||
return v.fpoint();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(ctx.positions[pos], errorCtx);
|
||||
throw;
|
||||
@@ -2179,19 +2183,19 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).atPos(pos).debugThrow();
|
||||
return v.boolean;
|
||||
return v.boolean();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(ctx.positions[pos], errorCtx);
|
||||
throw;
|
||||
}
|
||||
|
||||
return v.boolean;
|
||||
return v.boolean();
|
||||
}
|
||||
|
||||
|
||||
bool EvalState::isFunctor(Value & fun)
|
||||
{
|
||||
return fun.type() == nAttrs && fun.attrs->get(ctx.s.functor);
|
||||
return fun.type() == nAttrs && fun.attrs()->get(ctx.s.functor);
|
||||
}
|
||||
|
||||
|
||||
@@ -2232,8 +2236,8 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
|
||||
|
||||
void copyContext(const Value & v, NixStringContext & context)
|
||||
{
|
||||
if (v.string.context)
|
||||
for (const char * * p = v.string.context; *p; ++p)
|
||||
if (v.string().context)
|
||||
for (const char * * p = v.string().context; *p; ++p)
|
||||
context.insert(NixStringContextElem::parse(*p));
|
||||
}
|
||||
|
||||
@@ -2249,12 +2253,12 @@ std::string_view EvalState::forceString(Value & v, NixStringContext & context, c
|
||||
std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
{
|
||||
auto s = forceString(v, pos, errorCtx);
|
||||
if (v.string.context) {
|
||||
if (v.string().context) {
|
||||
ctx.errors
|
||||
.make<EvalError>(
|
||||
"the string '%1%' is not allowed to refer to a store path (such as '%2%')",
|
||||
v.str(),
|
||||
v.string.context[0]
|
||||
v.string().context[0]
|
||||
)
|
||||
.withTrace(pos, errorCtx)
|
||||
.debugThrow();
|
||||
@@ -2266,7 +2270,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.s.type);
|
||||
if (!i) {
|
||||
return false;
|
||||
}
|
||||
@@ -2279,7 +2283,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.s.toString);
|
||||
if (i) {
|
||||
Value v1;
|
||||
try {
|
||||
@@ -2328,7 +2332,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.s.outPath);
|
||||
if (!i) {
|
||||
ctx.errors.make<TypeError>(
|
||||
"cannot coerce %1% to a string: %2%",
|
||||
@@ -2344,7 +2348,7 @@ BackedStringView EvalState::coerceToString(
|
||||
|
||||
if (v.type() == nExternal) {
|
||||
try {
|
||||
return v.external->coerceToString(*this, pos, context, mode, copyToStore);
|
||||
return v.external()->coerceToString(*this, pos, context, mode, copyToStore);
|
||||
} catch (Error & e) {
|
||||
e.addTrace(nullptr, errorCtx);
|
||||
throw;
|
||||
@@ -2354,15 +2358,21 @@ BackedStringView EvalState::coerceToString(
|
||||
/* Raito: Any addition to this mode is subject to extra scrutiny
|
||||
* until we have better formatting tools. */
|
||||
if (mode >= StringCoercionMode::Interpolation) {
|
||||
if (v.type() == nInt) return std::to_string(v.integer.value);
|
||||
if (v.type() == nInt) {
|
||||
return std::to_string(v.integer().value);
|
||||
}
|
||||
}
|
||||
|
||||
if (mode >= StringCoercionMode::ToString) {
|
||||
/* Note that `false' is represented as an empty string for
|
||||
shell scripting convenience, just like `null'. */
|
||||
if (v.type() == nBool && v.boolean) return "1";
|
||||
if (v.type() == nBool && !v.boolean) return "";
|
||||
if (v.type() == nFloat) return std::to_string(v.fpoint);
|
||||
if (v.type() == nBool && v.boolean()) {
|
||||
return "1";
|
||||
}
|
||||
if (v.type() == nBool && !v.boolean()) {
|
||||
return "";
|
||||
}
|
||||
if (v.type() == nFloat) return std::to_string(v.fpoint());
|
||||
if (v.type() == nNull) return "";
|
||||
|
||||
if (v.isList()) {
|
||||
@@ -2512,20 +2522,22 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
||||
if (&v1 == &v2) return true;
|
||||
|
||||
// Special case type-compatibility between float and int
|
||||
if (v1.type() == nInt && v2.type() == nFloat)
|
||||
return v1.integer.value == v2.fpoint;
|
||||
if (v1.type() == nFloat && v2.type() == nInt)
|
||||
return v1.fpoint == v2.integer.value;
|
||||
if (v1.type() == nInt && v2.type() == nFloat) {
|
||||
return v1.integer().value == v2.fpoint();
|
||||
}
|
||||
if (v1.type() == nFloat && v2.type() == nInt) {
|
||||
return v1.fpoint() == v2.integer().value;
|
||||
}
|
||||
|
||||
// All other types are not compatible with each other.
|
||||
if (v1.type() != v2.type()) return false;
|
||||
|
||||
switch (v1.type()) {
|
||||
case nInt:
|
||||
return v1.integer == v2.integer;
|
||||
return v1.integer() == v2.integer();
|
||||
|
||||
case nBool:
|
||||
return v1.boolean == v2.boolean;
|
||||
return v1.boolean() == v2.boolean();
|
||||
|
||||
case nString:
|
||||
return v1.str() == v2.str();
|
||||
@@ -2546,18 +2558,18 @@ 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.s.outPath);
|
||||
auto j = v2.attrs()->get(ctx.s.outPath);
|
||||
if (i && j) {
|
||||
return eqValues(*i->value, *j->value, pos, errorCtx);
|
||||
}
|
||||
}
|
||||
|
||||
if (v1.attrs->size() != v2.attrs->size()) return false;
|
||||
if (v1.attrs()->size() != v2.attrs()->size()) return false;
|
||||
|
||||
/* Otherwise, compare the attributes one by one. */
|
||||
Bindings::iterator i, j;
|
||||
for (i = v1.attrs->begin(), j = v2.attrs->begin(); i != v1.attrs->end(); ++i, ++j)
|
||||
for (i = v1.attrs()->begin(), j = v2.attrs()->begin(); i != v1.attrs()->end(); ++i, ++j)
|
||||
if (i->name != j->name || !eqValues(*i->value, *j->value, pos, errorCtx))
|
||||
return false;
|
||||
|
||||
@@ -2569,10 +2581,10 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
||||
return false;
|
||||
|
||||
case nExternal:
|
||||
return *v1.external == *v2.external;
|
||||
return *v1.external() == *v2.external();
|
||||
|
||||
case nFloat:
|
||||
return v1.fpoint == v2.fpoint;
|
||||
return v1.fpoint() == v2.fpoint();
|
||||
|
||||
case nThunk: // Must not be left by forceValue
|
||||
default:
|
||||
|
||||
+16
-17
@@ -114,10 +114,10 @@ static void parseFlakeInputAttr(EvalState & state, const Attr & attr, fetchers::
|
||||
attrs.emplace(state.ctx.symbols[attr.name], std::string(attr.value->str()));
|
||||
break;
|
||||
case nBool:
|
||||
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean});
|
||||
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
|
||||
break;
|
||||
case nInt: {
|
||||
auto intValue = attr.value->integer.value;
|
||||
auto intValue = attr.value->integer().value;
|
||||
|
||||
if (intValue < 0) {
|
||||
state.ctx.errors
|
||||
@@ -160,7 +160,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||
fetchers::Attrs attrs;
|
||||
std::optional<std::string> url;
|
||||
|
||||
for (nix::Attr attr : *(value->attrs)) {
|
||||
for (nix::Attr attr : *(value->attrs())) {
|
||||
try {
|
||||
if (attr.name == sUrl) {
|
||||
expectType(state, nString, *attr.value, attr.pos);
|
||||
@@ -168,7 +168,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
||||
attrs.emplace("url", *url);
|
||||
} else if (attr.name == sFlake) {
|
||||
expectType(state, nBool, *attr.value, attr.pos);
|
||||
input.isFlake = attr.value->boolean;
|
||||
input.isFlake = attr.value->boolean();
|
||||
} else if (attr.name == sInputs) {
|
||||
input.overrides =
|
||||
parseFlakeInputs(
|
||||
@@ -231,7 +231,7 @@ static std::pair<std::map<FlakeId, FlakeInput>, std::optional<fetchers::Attrs>>
|
||||
expectType(state, nAttrs, *value, pos);
|
||||
|
||||
std::optional<fetchers::Attrs> selfAttrs = std::nullopt;
|
||||
for (const nix::Attr & inputAttr : *(*value).attrs) {
|
||||
for (const nix::Attr & inputAttr : *(*value).attrs()) {
|
||||
std::string inputName{state.ctx.symbols[inputAttr.name]};
|
||||
if (inputName == "self") {
|
||||
experimentalFeatureSettings.require(Xp::FlakeSelfAttrs);
|
||||
@@ -244,7 +244,7 @@ static std::pair<std::map<FlakeId, FlakeInput>, std::optional<fetchers::Attrs>>
|
||||
expectType(state, nAttrs, *inputAttr.value, inputAttr.pos);
|
||||
|
||||
selfAttrs = selfAttrs.value_or(fetchers::Attrs{});
|
||||
for (auto & attr : *inputAttr.value->attrs) {
|
||||
for (auto & attr : *inputAttr.value->attrs()) {
|
||||
parseFlakeInputAttr(state, attr, *selfAttrs);
|
||||
}
|
||||
} else {
|
||||
@@ -328,14 +328,14 @@ 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.s.description)) {
|
||||
expectType(state, nString, *description->value, description->pos);
|
||||
flake.description = description->value->str();
|
||||
}
|
||||
|
||||
auto sInputs = state.ctx.symbols.create("inputs");
|
||||
|
||||
if (auto inputs = vInfo.attrs->get(sInputs)) {
|
||||
if (auto inputs = vInfo.attrs()->get(sInputs)) {
|
||||
auto [flakeInputs, selfAttrs] =
|
||||
parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath, 0, true);
|
||||
flake.inputs = std::move(flakeInputs);
|
||||
@@ -361,11 +361,11 @@ static Flake getFlake(
|
||||
flake.resolvedRef = resolvedRef;
|
||||
}
|
||||
|
||||
if (auto outputs = vInfo.attrs->get(state.ctx.s.outputs)) {
|
||||
if (auto outputs = vInfo.attrs()->get(state.ctx.s.outputs)) {
|
||||
expectType(state, nFunction, *outputs->value, outputs->pos);
|
||||
|
||||
if (outputs->value->isLambda()) {
|
||||
if (auto pattern = dynamic_cast<AttrsPattern *>(outputs->value->lambda.fun->pattern.get()); pattern) {
|
||||
if (auto pattern = dynamic_cast<AttrsPattern *>(outputs->value->lambda().fun->pattern.get()); pattern) {
|
||||
for (auto & formal : pattern->formals) {
|
||||
if (formal.name != state.ctx.s.self)
|
||||
flake.inputs.emplace(
|
||||
@@ -383,10 +383,10 @@ static Flake getFlake(
|
||||
|
||||
auto sNixConfig = state.ctx.symbols.create("nixConfig");
|
||||
|
||||
if (auto nixConfig = vInfo.attrs->get(sNixConfig)) {
|
||||
if (auto nixConfig = vInfo.attrs()->get(sNixConfig)) {
|
||||
expectType(state, nAttrs, *nixConfig->value, nixConfig->pos);
|
||||
|
||||
for (auto & setting : *nixConfig->value->attrs) {
|
||||
for (auto & setting : *nixConfig->value->attrs()) {
|
||||
forceTrivialValue(state, *setting.value, setting.pos);
|
||||
if (setting.value->type() == nString)
|
||||
flake.config.settings.emplace(
|
||||
@@ -422,7 +422,7 @@ static Flake getFlake(
|
||||
}
|
||||
}
|
||||
|
||||
for (auto & attr : *vInfo.attrs) {
|
||||
for (auto & attr : *vInfo.attrs()) {
|
||||
if (attr.name != state.ctx.s.description &&
|
||||
attr.name != sInputs &&
|
||||
attr.name != state.ctx.s.outputs &&
|
||||
@@ -984,10 +984,10 @@ void prim_flakeRefToString(
|
||||
state.forceAttrs(*args[0], noPos,
|
||||
"while evaluating the argument passed to builtins.flakeRefToString");
|
||||
fetchers::Attrs attrs;
|
||||
for (const auto & attr : *args[0]->attrs) {
|
||||
for (const auto & attr : *args[0]->attrs()) {
|
||||
auto t = attr.value->type();
|
||||
if (t == nInt) {
|
||||
auto intValue = attr.value->integer.value;
|
||||
auto intValue = attr.value->integer().value;
|
||||
|
||||
if (intValue < 0) {
|
||||
state.ctx.errors.make<EvalError>("negative value given for flake ref attr %1%: %2%", state.ctx.symbols[attr.name], intValue).debugThrow();
|
||||
@@ -996,8 +996,7 @@ void prim_flakeRefToString(
|
||||
|
||||
attrs.emplace(state.ctx.symbols[attr.name], asUnsigned);
|
||||
} else if (t == nBool) {
|
||||
attrs.emplace(state.ctx.symbols[attr.name],
|
||||
Explicit<bool> { attr.value->boolean });
|
||||
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
|
||||
} else if (t == nString) {
|
||||
attrs.emplace(state.ctx.symbols[attr.name],
|
||||
std::string(attr.value->str()));
|
||||
|
||||
+15
-11
@@ -187,7 +187,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.s.outPath);
|
||||
if (outPath == nullptr) {
|
||||
continue;
|
||||
// FIXME: throw error?
|
||||
@@ -291,7 +291,7 @@ Bindings * DrvInfo::getMeta(EvalState & state)
|
||||
return 0;
|
||||
}
|
||||
state.forceAttrs(*a->value, a->pos, "while evaluating the 'meta' attribute of a derivation");
|
||||
meta = a->value->attrs;
|
||||
meta = a->value->attrs();
|
||||
return meta;
|
||||
}
|
||||
|
||||
@@ -315,11 +315,11 @@ 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.s.outPath);
|
||||
if (i) {
|
||||
return false;
|
||||
}
|
||||
for (auto & i : *v.attrs)
|
||||
for (auto & i : *v.attrs())
|
||||
if (!checkMeta(state, *i.value)) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -351,7 +351,9 @@ NixInt DrvInfo::queryMetaInt(EvalState & state, const std::string & name, NixInt
|
||||
{
|
||||
Value * v = queryMeta(state, name);
|
||||
if (!v) return def;
|
||||
if (v->type() == nInt) return v->integer;
|
||||
if (v->type() == nInt) {
|
||||
return v->integer();
|
||||
}
|
||||
if (v->type() == nString) {
|
||||
/* Backwards compatibility with before we had support for
|
||||
integer meta fields. */
|
||||
@@ -366,7 +368,9 @@ bool DrvInfo::queryMetaBool(EvalState & state, const std::string & name, bool de
|
||||
{
|
||||
Value * v = queryMeta(state, name);
|
||||
if (!v) return def;
|
||||
if (v->type() == nBool) return v->boolean;
|
||||
if (v->type() == nBool) {
|
||||
return v->boolean();
|
||||
}
|
||||
if (v->type() == nString) {
|
||||
/* Backwards compatibility with before we had support for
|
||||
Boolean meta fields. */
|
||||
@@ -409,7 +413,7 @@ static bool getDerivation(EvalState & state, Value & v,
|
||||
state.forceValue(v, noPos);
|
||||
if (!state.isDerivation(v)) return true;
|
||||
|
||||
DrvInfo drv(attrPath, v.attrs);
|
||||
DrvInfo drv(attrPath, v.attrs());
|
||||
|
||||
drv.queryName(state);
|
||||
|
||||
@@ -489,7 +493,7 @@ static void getDerivations(EvalState & state, Value & vIn, PosIdx pos,
|
||||
|
||||
/* Dont consider sets we've already seen, e.g. y in
|
||||
`rec { x.d = derivation {...}; y = x; }`. */
|
||||
auto const &[_, didInsert] = done.insert(v.attrs);
|
||||
auto const &[_, didInsert] = done.insert(v.attrs());
|
||||
if (!didInsert) {
|
||||
return;
|
||||
}
|
||||
@@ -497,14 +501,14 @@ static void getDerivations(EvalState & state, Value & vIn, PosIdx pos,
|
||||
// FIXME: what the fuck???
|
||||
/* !!! undocumented hackery to support combining channels in
|
||||
nix-env.cc. */
|
||||
bool combineChannels = v.attrs->get(state.ctx.symbols.create("_combineChannels"));
|
||||
bool combineChannels = v.attrs()->get(state.ctx.symbols.create("_combineChannels"));
|
||||
|
||||
/* Consider the attributes in sorted order to get more
|
||||
deterministic behaviour in nix-env operations (e.g. when
|
||||
there are names clashes between derivations, the derivation
|
||||
bound to the attribute with the "lower" name should take
|
||||
precedence). */
|
||||
for (auto & attr : v.attrs->lexicographicOrder(state.ctx.symbols)) {
|
||||
for (auto & attr : v.attrs()->lexicographicOrder(state.ctx.symbols)) {
|
||||
debug("evaluating attribute '%1%'", state.ctx.symbols[attr->name]);
|
||||
// FIXME: only consider attrs with identifier-like names?? Why???
|
||||
if (!std::regex_match(std::string(state.ctx.symbols[attr->name]), attrRegex)) {
|
||||
@@ -528,7 +532,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.s.recurseForDerivations);
|
||||
if (recurseForDrvs == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ JSON ExprLiteral::toJSON(const SymbolTable & symbols) const
|
||||
switch (v.type()) {
|
||||
case nInt:
|
||||
valueType = "Int";
|
||||
value = v.integer.value;
|
||||
value = v.integer().value;
|
||||
break;
|
||||
case nFloat:
|
||||
valueType = "Float";
|
||||
value = v.fpoint;
|
||||
value = v.fpoint();
|
||||
break;
|
||||
case nString:
|
||||
valueType = "String";
|
||||
|
||||
+49
-51
@@ -226,16 +226,16 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v)
|
||||
else {
|
||||
state.forceAttrs(*vScope, noPos, "while evaluating the first argument passed to builtins.scopedImport");
|
||||
|
||||
Env * env = &state.ctx.mem.allocEnv(vScope->attrs->size());
|
||||
Env * env = &state.ctx.mem.allocEnv(vScope->attrs()->size());
|
||||
env->up = &state.ctx.builtins.env;
|
||||
|
||||
auto staticEnv = std::make_shared<StaticEnv>(
|
||||
nullptr, state.ctx.builtins.staticEnv.get(), vScope->attrs->size()
|
||||
nullptr, state.ctx.builtins.staticEnv.get(), vScope->attrs()->size()
|
||||
);
|
||||
|
||||
staticEnv->vars.unsafe_insert_bulk([&] (auto & map) {
|
||||
unsigned int displ = 0;
|
||||
for (auto & attr : *vScope->attrs) {
|
||||
for (auto & attr : *vScope->attrs()) {
|
||||
// safety: args[0]->attrs is already sorted.
|
||||
map.emplace_back(attr.name, displ);
|
||||
env->values[displ++] = attr.value;
|
||||
@@ -352,7 +352,7 @@ static void prim_typeOf(EvalState & state, Value * * args, Value & v)
|
||||
case nList: t = "list"; break;
|
||||
case nFunction: t = "lambda"; break;
|
||||
case nExternal:
|
||||
t = args[0]->external->typeOf();
|
||||
t = args[0]->external()->typeOf();
|
||||
break;
|
||||
case nFloat: t = "float"; break;
|
||||
case nThunk: abort();
|
||||
@@ -438,10 +438,12 @@ struct CompareValues : NeverAsync
|
||||
bool operator () (Value * v1, Value * v2, std::string_view errorCtx) const
|
||||
{
|
||||
try {
|
||||
if (v1->type() == nFloat && v2->type() == nInt)
|
||||
return v1->fpoint < v2->integer.value;
|
||||
if (v1->type() == nInt && v2->type() == nFloat)
|
||||
return v1->integer.value < v2->fpoint;
|
||||
if (v1->type() == nFloat && v2->type() == nInt) {
|
||||
return v1->fpoint() < v2->integer().value;
|
||||
}
|
||||
if (v1->type() == nInt && v2->type() == nFloat) {
|
||||
return v1->integer().value < v2->fpoint();
|
||||
}
|
||||
if (v1->type() != v2->type())
|
||||
state.ctx.errors.make<EvalError>("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow();
|
||||
// Allow selecting a subset of enum values
|
||||
@@ -449,9 +451,9 @@ struct CompareValues : NeverAsync
|
||||
#pragma GCC diagnostic ignored "-Wswitch-enum"
|
||||
switch (v1->type()) {
|
||||
case nInt:
|
||||
return v1->integer < v2->integer;
|
||||
return v1->integer() < v2->integer();
|
||||
case nFloat:
|
||||
return v1->fpoint < v2->fpoint;
|
||||
return v1->fpoint() < v2->fpoint();
|
||||
case nString:
|
||||
return v1->str() < v2->str();
|
||||
case nPath:
|
||||
@@ -504,7 +506,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
|
||||
auto startSet = getAttr(
|
||||
state,
|
||||
state.ctx.s.startSet,
|
||||
args[0]->attrs,
|
||||
args[0]->attrs(),
|
||||
"in the attrset passed as argument to builtins.genericClosure"
|
||||
);
|
||||
|
||||
@@ -523,7 +525,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
|
||||
auto op = getAttr(
|
||||
state,
|
||||
state.ctx.s.operator_,
|
||||
args[0]->attrs,
|
||||
args[0]->attrs(),
|
||||
"in the attrset passed as argument to builtins.genericClosure"
|
||||
);
|
||||
state.forceFunction(*op->value, noPos, "while evaluating the 'operator' attribute passed as argument to builtins.genericClosure");
|
||||
@@ -545,7 +547,7 @@ static void prim_genericClosure(EvalState & state, Value * * args, Value & v)
|
||||
auto key = getAttr(
|
||||
state,
|
||||
state.ctx.s.key,
|
||||
e->attrs,
|
||||
e->attrs(),
|
||||
"in one of the attrsets generated by (or initially passed to) builtins.genericClosure"
|
||||
);
|
||||
state.forceValue(*key->value, noPos);
|
||||
@@ -747,7 +749,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
state.forceAttrs(*args[0], noPos, "while evaluating the argument passed to builtins.derivationStrict");
|
||||
|
||||
Bindings * attrs = args[0]->attrs;
|
||||
Bindings * attrs = args[0]->attrs();
|
||||
|
||||
/* Figure out the name first (for stack backtraces). */
|
||||
auto nameAttr = getAttr(
|
||||
@@ -1305,7 +1307,7 @@ static void prim_findFile(EvalState & state, Value * * args, Value & v)
|
||||
state.forceAttrs(*v2, noPos, "while evaluating an element of the list passed to builtins.findFile");
|
||||
|
||||
std::string prefix;
|
||||
auto i = v2->attrs->get(state.ctx.s.prefix);
|
||||
auto i = v2->attrs()->get(state.ctx.s.prefix);
|
||||
if (i) {
|
||||
prefix = state.forceStringNoCtx(
|
||||
*i->value,
|
||||
@@ -1315,7 +1317,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.s.path, v2->attrs(), "in an element of the __nixPath");
|
||||
|
||||
NixStringContext context;
|
||||
auto path = state.coerceToString(noPos, *i->value, context,
|
||||
@@ -1602,7 +1604,7 @@ static void prim_path(EvalState & state, Value * * args, Value & v)
|
||||
|
||||
state.forceAttrs(*args[0], noPos, "while evaluating the argument passed to 'builtins.path'");
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
for (auto & attr : *args[0]->attrs()) {
|
||||
auto & n = state.ctx.symbols[attr.name];
|
||||
if (n == "path")
|
||||
path.emplace(state.coerceToPath(attr.pos, *attr.value, context, "while evaluating the 'path' attribute passed to 'builtins.path'"));
|
||||
@@ -1642,10 +1644,10 @@ static void prim_attrNames(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
state.forceAttrs(*args[0], noPos, "while evaluating the argument passed to builtins.attrNames");
|
||||
|
||||
v = state.ctx.mem.newList(args[0]->attrs->size());
|
||||
v = state.ctx.mem.newList(args[0]->attrs()->size());
|
||||
|
||||
size_t n = 0;
|
||||
for (auto & i : *args[0]->attrs)
|
||||
for (auto & i : *args[0]->attrs())
|
||||
v.listElems()[n++] = const_cast<Value *>(state.ctx.symbols[i.name].toValuePtr());
|
||||
|
||||
std::sort(v.listElems(), v.listElems() + n, [](Value * v1, Value * v2) {
|
||||
@@ -1659,12 +1661,12 @@ static void prim_attrValues(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
state.forceAttrs(*args[0], noPos, "while evaluating the argument passed to builtins.attrValues");
|
||||
|
||||
v = state.ctx.mem.newList(args[0]->attrs->size());
|
||||
v = state.ctx.mem.newList(args[0]->attrs()->size());
|
||||
|
||||
// FIXME: this is incredibly evil, *why*
|
||||
// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
|
||||
unsigned int n = 0;
|
||||
for (auto & i : *args[0]->attrs)
|
||||
for (auto & i : *args[0]->attrs())
|
||||
v.listElems()[n++] = (Value *) &i;
|
||||
|
||||
std::sort(v.listElems(), v.listElems() + n,
|
||||
@@ -1687,7 +1689,7 @@ void prim_getAttr(EvalState & state, Value * * args, Value & v)
|
||||
auto i = getAttr(
|
||||
state,
|
||||
state.ctx.symbols.create(attr),
|
||||
args[1]->attrs,
|
||||
args[1]->attrs(),
|
||||
"in the attribute set under consideration"
|
||||
);
|
||||
// !!! add to stack trace?
|
||||
@@ -1701,7 +1703,7 @@ static void prim_unsafeGetAttrPos(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
auto attr = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.unsafeGetAttrPos");
|
||||
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.unsafeGetAttrPos");
|
||||
auto i = args[1]->attrs->get(state.ctx.symbols.create(attr));
|
||||
auto i = args[1]->attrs()->get(state.ctx.symbols.create(attr));
|
||||
if (!i) {
|
||||
v.mkNull();
|
||||
} else {
|
||||
@@ -1722,18 +1724,14 @@ static void prim_unsafeGetAttrPos(EvalState & state, Value * * args, Value & v)
|
||||
// as with black holes this cost is too high to justify another thunk type to check
|
||||
// for in the very hot path that is forceValue.
|
||||
static struct LazyPosAcessors {
|
||||
PrimOp primop_lineOfPos{
|
||||
.arity = 1,
|
||||
.fun = [] (EvalState & state, Value * * args, Value & v) {
|
||||
v.mkInt(state.ctx.positions[PosIdx(args[0]->integer.value)].line);
|
||||
}
|
||||
};
|
||||
PrimOp primop_columnOfPos{
|
||||
.arity = 1,
|
||||
.fun = [] (EvalState & state, Value * * args, Value & v) {
|
||||
v.mkInt(state.ctx.positions[PosIdx(args[0]->integer.value)].column);
|
||||
}
|
||||
};
|
||||
PrimOp primop_lineOfPos{.arity = 1, .fun = [](EvalState & state, Value ** args, Value & v) {
|
||||
v.mkInt(state.ctx.positions[PosIdx(args[0]->integer().value)].line);
|
||||
}};
|
||||
PrimOp primop_columnOfPos{.arity = 1, .fun = [](EvalState & state, Value ** args, Value & v) {
|
||||
v.mkInt(
|
||||
state.ctx.positions[PosIdx(args[0]->integer().value)].column
|
||||
);
|
||||
}};
|
||||
|
||||
Value lineOfPos, columnOfPos;
|
||||
|
||||
@@ -1762,7 +1760,7 @@ static void prim_hasAttr(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
auto attr = state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.hasAttr");
|
||||
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.hasAttr");
|
||||
v.mkBool(args[1]->attrs->get(state.ctx.symbols.create(attr)));
|
||||
v.mkBool(args[1]->attrs()->get(state.ctx.symbols.create(attr)));
|
||||
}
|
||||
|
||||
/* Determine whether the argument is a set. */
|
||||
@@ -1792,9 +1790,9 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
|
||||
/* Copy all attributes not in that set. Note that we don't need
|
||||
to sort v.attrs because it's a subset of an already sorted
|
||||
vector. */
|
||||
auto attrs = state.ctx.buildBindings(args[0]->attrs->size());
|
||||
auto attrs = state.ctx.buildBindings(args[0]->attrs()->size());
|
||||
std::set_difference(
|
||||
args[0]->attrs->begin(), args[0]->attrs->end(),
|
||||
args[0]->attrs()->begin(), args[0]->attrs()->end(),
|
||||
names.begin(), names.end(),
|
||||
std::back_inserter(attrs));
|
||||
v.mkAttrs(attrs.alreadySorted());
|
||||
@@ -1816,14 +1814,14 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
|
||||
for (auto v2 : args[0]->listItems()) {
|
||||
state.forceAttrs(*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.s.name, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||
|
||||
auto name = state.forceStringNoCtx(*j->value, j->pos, "while evaluating the `name` attribute of an element of the list passed to builtins.listToAttrs");
|
||||
|
||||
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.s.value, v2->attrs(), "in a {name=...; value=...;} pair");
|
||||
attrs.insert(sym, j2->value, j2->pos);
|
||||
}
|
||||
}
|
||||
@@ -1836,8 +1834,8 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v)
|
||||
state.forceAttrs(*args[0], noPos, "while evaluating the first argument passed to builtins.intersectAttrs");
|
||||
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.intersectAttrs");
|
||||
|
||||
Bindings &left = *args[0]->attrs;
|
||||
Bindings &right = *args[1]->attrs;
|
||||
Bindings &left = *args[0]->attrs();
|
||||
Bindings &right = *args[1]->attrs();
|
||||
|
||||
auto attrs = state.ctx.buildBindings(std::min(left.size(), right.size()));
|
||||
|
||||
@@ -1909,7 +1907,7 @@ static void prim_catAttrs(EvalState & state, Value * * args, Value & v)
|
||||
|
||||
for (auto v2 : args[1]->listItems()) {
|
||||
state.forceAttrs(*v2, noPos, "while evaluating an element in the list passed as second argument to builtins.catAttrs");
|
||||
auto i = v2->attrs->get(attrName);
|
||||
auto i = v2->attrs()->get(attrName);
|
||||
if (i) {
|
||||
res[found++] = i->value;
|
||||
}
|
||||
@@ -1931,7 +1929,7 @@ static void prim_functionArgs(EvalState & state, Value * * args, Value & v)
|
||||
if (!args[0]->isLambda())
|
||||
state.ctx.errors.make<TypeError>("'functionArgs' requires a function").debugThrow();
|
||||
|
||||
AttrsPattern * formals = dynamic_cast<AttrsPattern *>(args[0]->lambda.fun->pattern.get());
|
||||
AttrsPattern * formals = dynamic_cast<AttrsPattern *>(args[0]->lambda().fun->pattern.get());
|
||||
if (!formals) {
|
||||
v.mkAttrs(&Bindings::EMPTY);
|
||||
return;
|
||||
@@ -1949,9 +1947,9 @@ static void prim_mapAttrs(EvalState & state, Value * * args, Value & v)
|
||||
{
|
||||
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.mapAttrs");
|
||||
|
||||
auto attrs = state.ctx.buildBindings(args[1]->attrs->size());
|
||||
auto attrs = state.ctx.buildBindings(args[1]->attrs()->size());
|
||||
|
||||
for (auto & i : *args[1]->attrs) {
|
||||
for (auto & i : *args[1]->attrs()) {
|
||||
Value * vFun2 = state.ctx.mem.allocValue();
|
||||
auto vName = const_cast<Value *>(state.ctx.symbols[i.name].toValuePtr());
|
||||
vFun2->mkApp(args[0], vName);
|
||||
@@ -1980,7 +1978,7 @@ static void prim_zipAttrsWith(EvalState & state, Value * * args, Value & v)
|
||||
for (unsigned int n = 0; n < listSize; ++n) {
|
||||
Value * vElem = listElems[n];
|
||||
state.forceAttrs(*vElem, noPos, "while evaluating a value of the list passed as second argument to builtins.zipAttrsWith");
|
||||
for (auto & attr : *vElem->attrs)
|
||||
for (auto & attr : *vElem->attrs())
|
||||
attrsSeen[attr.name].first++;
|
||||
}
|
||||
|
||||
@@ -2005,7 +2003,7 @@ static void prim_zipAttrsWith(EvalState & state, Value * * args, Value & v)
|
||||
/* Populate the lists inside the attribute set */
|
||||
for (unsigned int n = 0; n < listSize; ++n) {
|
||||
Value * vElem = listElems[n];
|
||||
for (auto & attr : *vElem->attrs) {
|
||||
for (auto & attr : *vElem->attrs()) {
|
||||
*attrsSeen[attr.name].second++ = attr.value;
|
||||
}
|
||||
}
|
||||
@@ -2249,7 +2247,7 @@ static void prim_sort(EvalState & state, Value * * args, Value & v)
|
||||
/* TODO: (layus) this is absurd. An optimisation like this
|
||||
should be outside the lambda creation */
|
||||
if (args[0]->isPrimOp()) {
|
||||
auto ptr = args[0]->primOp->fun.target<decltype(&prim_lessThan)>();
|
||||
auto ptr = args[0]->primOp()->fun.target<decltype(&prim_lessThan)>();
|
||||
if (ptr && *ptr == prim_lessThan)
|
||||
return CompareValues(state, "while evaluating the ordering function passed to builtins.sort")(a, b);
|
||||
}
|
||||
@@ -2525,7 +2523,7 @@ static void prim_substring(EvalState & state, Value * * args, Value & v)
|
||||
if (len_arg == 0) {
|
||||
state.forceValue(*args[2], noPos);
|
||||
if (args[2]->type() == nString) {
|
||||
v.mkString("", args[2]->string.context);
|
||||
v.mkString("", args[2]->string().context);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2888,7 +2886,7 @@ void EvalBuiltins::createBaseEnv(const SearchPath & searchPath, const Path & sto
|
||||
|
||||
/* Now that we've added all primops, sort the `builtins' set,
|
||||
because attribute lookups expect it to be sorted. */
|
||||
env.values[0]->attrs->sort();
|
||||
env.values[0]->attrs()->sort();
|
||||
|
||||
staticEnv->isRoot = true;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ static void prim_appendContext(EvalState & state, Value * * args, Value & v)
|
||||
state.forceAttrs(*args[1], noPos, "while evaluating the second argument passed to builtins.appendContext");
|
||||
|
||||
auto sAllOutputs = state.ctx.symbols.create("allOutputs");
|
||||
for (auto & i : *args[1]->attrs) {
|
||||
for (auto & i : *args[1]->attrs()) {
|
||||
const auto & name = state.ctx.symbols[i.name];
|
||||
if (!state.ctx.store->isStorePath(name))
|
||||
state.ctx.errors.make<EvalError>(
|
||||
@@ -182,7 +182,7 @@ static 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.s.path);
|
||||
if (a) {
|
||||
if (state.forceBool(
|
||||
*a->value, a->pos, "while evaluating the `path` attribute of a string context"
|
||||
@@ -194,7 +194,7 @@ static void prim_appendContext(EvalState & state, Value * * args, Value & v)
|
||||
}
|
||||
}
|
||||
|
||||
a = i.value->attrs->get(sAllOutputs);
|
||||
a = i.value->attrs()->get(sAllOutputs);
|
||||
if (a) {
|
||||
if (state.forceBool(
|
||||
*a->value,
|
||||
@@ -214,7 +214,7 @@ static 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.s.outputs);
|
||||
if (a) {
|
||||
state.forceList(
|
||||
*a->value, a->pos, "while evaluating the `outputs` attribute of a string context"
|
||||
|
||||
@@ -118,7 +118,7 @@ void prim_fetchClosure(EvalState & state, Value * * args, Value & v)
|
||||
std::optional<StorePathOrGap> toPath;
|
||||
std::optional<bool> inputAddressedMaybe;
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
for (auto & attr : *args[0]->attrs()) {
|
||||
const auto & attrName = state.ctx.symbols[attr.name];
|
||||
auto attrHint = [&]() -> std::string {
|
||||
return "while evaluating the '" + attrName + "' attribute passed to builtins.fetchClosure";
|
||||
|
||||
@@ -17,7 +17,7 @@ static void prim_fetchMercurial(EvalState & state, Value * * args, Value & v)
|
||||
|
||||
if (args[0]->type() == nAttrs) {
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
for (auto & attr : *args[0]->attrs()) {
|
||||
std::string_view n(state.ctx.symbols[attr.name]);
|
||||
if (n == "url")
|
||||
url = state.coerceToString(attr.pos, *attr.value, context,
|
||||
|
||||
@@ -122,7 +122,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.s.type)) {
|
||||
if (type)
|
||||
state.ctx.errors.make<EvalError>(
|
||||
"unexpected attribute 'type'"
|
||||
@@ -135,7 +135,7 @@ static void fetchTree(
|
||||
|
||||
attrs.emplace("type", type.value());
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
for (auto & attr : *args[0]->attrs()) {
|
||||
if (attr.name == state.ctx.s.type) continue;
|
||||
state.forceValue(*attr.value, attr.pos);
|
||||
if (attr.value->type() == nPath || attr.value->type() == nString) {
|
||||
@@ -148,9 +148,9 @@ static void fetchTree(
|
||||
: s);
|
||||
}
|
||||
else if (attr.value->type() == nBool)
|
||||
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean});
|
||||
attrs.emplace(state.ctx.symbols[attr.name], Explicit<bool>{attr.value->boolean()});
|
||||
else if (attr.value->type() == nInt) {
|
||||
auto intValue = attr.value->integer.value;
|
||||
auto intValue = attr.value->integer().value;
|
||||
|
||||
if (intValue < 0) {
|
||||
state.ctx.errors.make<EvalError>("negative value given for fetchTree attr %1%: %2%", state.ctx.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||
@@ -221,7 +221,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
|
||||
|
||||
if (args[0]->type() == nAttrs) {
|
||||
|
||||
for (auto & attr : *args[0]->attrs) {
|
||||
for (auto & attr : *args[0]->attrs()) {
|
||||
std::string_view n(state.ctx.symbols[attr.name]);
|
||||
if (n == "url")
|
||||
url = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the url we should fetch");
|
||||
|
||||
@@ -23,10 +23,10 @@ void printAmbiguous(
|
||||
}
|
||||
switch (v.type()) {
|
||||
case nInt:
|
||||
str << v.integer;
|
||||
str << v.integer();
|
||||
break;
|
||||
case nBool:
|
||||
printLiteralBool(str, v.boolean);
|
||||
printLiteralBool(str, v.boolean());
|
||||
break;
|
||||
case nString:
|
||||
escapeString(str, v.str());
|
||||
@@ -38,11 +38,11 @@ void printAmbiguous(
|
||||
str << "null";
|
||||
break;
|
||||
case nAttrs: {
|
||||
if (seen && !v.attrs->empty() && !seen->insert(v.attrs).second)
|
||||
if (seen && !v.attrs()->empty() && !seen->insert(v.attrs()).second)
|
||||
str << "«repeated»";
|
||||
else {
|
||||
str << "{ ";
|
||||
for (auto & i : v.attrs->lexicographicOrder(symbols)) {
|
||||
for (auto & i : v.attrs()->lexicographicOrder(symbols)) {
|
||||
str << symbols[i->name] << " = ";
|
||||
printAmbiguous(*i->value, symbols, str, seen, depth - 1);
|
||||
str << "; ";
|
||||
@@ -89,10 +89,10 @@ void printAmbiguous(
|
||||
}
|
||||
break;
|
||||
case nExternal:
|
||||
str << *v.external;
|
||||
str << *v.external();
|
||||
break;
|
||||
case nFloat:
|
||||
str << v.fpoint;
|
||||
str << v.fpoint();
|
||||
break;
|
||||
default:
|
||||
printError("Lix evaluator internal error: printAmbiguous: invalid value type");
|
||||
|
||||
+14
-14
@@ -177,7 +177,7 @@ private:
|
||||
{
|
||||
if (options.ansiColors)
|
||||
output << ANSI_CYAN;
|
||||
output << v.integer;
|
||||
output << v.integer();
|
||||
if (options.ansiColors)
|
||||
output << ANSI_NORMAL;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ private:
|
||||
{
|
||||
if (options.ansiColors)
|
||||
output << ANSI_CYAN;
|
||||
output << v.fpoint;
|
||||
output << v.fpoint();
|
||||
if (options.ansiColors)
|
||||
output << ANSI_NORMAL;
|
||||
}
|
||||
@@ -195,7 +195,7 @@ private:
|
||||
{
|
||||
if (options.ansiColors)
|
||||
output << ANSI_CYAN;
|
||||
printLiteralBool(output, v.boolean);
|
||||
printLiteralBool(output, v.boolean());
|
||||
if (options.ansiColors)
|
||||
output << ANSI_NORMAL;
|
||||
}
|
||||
@@ -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.s.drvPath);
|
||||
NixStringContext context;
|
||||
std::string storePath;
|
||||
if (i) {
|
||||
@@ -283,14 +283,14 @@ private:
|
||||
{
|
||||
if (options.force && options.derivationPaths && state.isDerivation(v)) {
|
||||
printDerivation(v);
|
||||
} else if (seen && !v.attrs->empty() && !seen->insert(v.attrs).second) {
|
||||
} else if (seen && !v.attrs()->empty() && !seen->insert(v.attrs()).second) {
|
||||
printRepeated();
|
||||
} else if (depth < options.maxDepth || v.attrs->empty()) {
|
||||
} else if (depth < options.maxDepth || v.attrs()->empty()) {
|
||||
increaseIndent();
|
||||
output << "{";
|
||||
|
||||
AttrVec sorted;
|
||||
for (auto & i : *v.attrs)
|
||||
for (auto & i : *v.attrs())
|
||||
sorted.emplace_back(state.ctx.symbols[i.name], &i);
|
||||
|
||||
if (options.maxAttrs == std::numeric_limits<size_t>::max())
|
||||
@@ -411,18 +411,18 @@ private:
|
||||
|
||||
if (v.isLambda()) {
|
||||
output << "lambda";
|
||||
if (v.lambda.fun) {
|
||||
if (v.lambda.fun->name) {
|
||||
output << " " << state.ctx.symbols[v.lambda.fun->name];
|
||||
if (v.lambda().fun) {
|
||||
if (v.lambda().fun->name) {
|
||||
output << " " << state.ctx.symbols[v.lambda().fun->name];
|
||||
}
|
||||
|
||||
std::ostringstream s;
|
||||
s << state.ctx.positions[v.lambda.fun->pos];
|
||||
s << state.ctx.positions[v.lambda().fun->pos];
|
||||
output << " @ " << filterANSIEscapes(s.str());
|
||||
}
|
||||
} else if (v.isPrimOp()) {
|
||||
if (v.primOp)
|
||||
output << *v.primOp;
|
||||
if (v.primOp())
|
||||
output << *v.primOp();
|
||||
else
|
||||
output << "primop";
|
||||
} else if (v.isPrimOpApp()) {
|
||||
@@ -468,7 +468,7 @@ private:
|
||||
|
||||
void printExternal(Value & v)
|
||||
{
|
||||
v.external->print(output);
|
||||
v.external()->print(output);
|
||||
}
|
||||
|
||||
void printUnknown()
|
||||
|
||||
@@ -19,11 +19,11 @@ JSON printValueAsJSON(EvalState & state, bool strict,
|
||||
switch (v.type()) {
|
||||
|
||||
case nInt:
|
||||
out = v.integer.value;
|
||||
out = v.integer().value;
|
||||
break;
|
||||
|
||||
case nBool:
|
||||
out = v.boolean;
|
||||
out = v.boolean();
|
||||
break;
|
||||
|
||||
case nString:
|
||||
@@ -51,14 +51,14 @@ 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.s.outPath);
|
||||
if (!i) {
|
||||
out = JSON::object();
|
||||
StringSet names;
|
||||
for (auto & j : *v.attrs)
|
||||
for (auto & j : *v.attrs())
|
||||
names.emplace(state.ctx.symbols[j.name]);
|
||||
for (auto & j : names) {
|
||||
const Attr & a(*v.attrs->get(state.ctx.symbols.create(j)));
|
||||
const Attr & a(*v.attrs()->get(state.ctx.symbols.create(j)));
|
||||
try {
|
||||
out[j] = printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
|
||||
} catch (Error & e) {
|
||||
@@ -90,11 +90,11 @@ JSON printValueAsJSON(EvalState & state, bool strict,
|
||||
}
|
||||
|
||||
case nExternal:
|
||||
return v.external->printValueAsJSON(state, strict, context, copyToStore);
|
||||
return v.external()->printValueAsJSON(state, strict, context, copyToStore);
|
||||
break;
|
||||
|
||||
case nFloat:
|
||||
out = v.fpoint;
|
||||
out = v.fpoint();
|
||||
break;
|
||||
|
||||
case nThunk:
|
||||
|
||||
+12
-12
@@ -60,11 +60,11 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||
switch (v.type()) {
|
||||
|
||||
case nInt:
|
||||
doc.writeEmptyElement("int", singletonAttrs("value", fmt("%1%", v.integer)));
|
||||
doc.writeEmptyElement("int", singletonAttrs("value", fmt("%1%", v.integer())));
|
||||
break;
|
||||
|
||||
case nBool:
|
||||
doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean ? "true" : "false"));
|
||||
doc.writeEmptyElement("bool", singletonAttrs("value", v.boolean() ? "true" : "false"));
|
||||
break;
|
||||
|
||||
case nString:
|
||||
@@ -85,17 +85,17 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||
if (state.isDerivation(v)) {
|
||||
XMLAttrs xmlAttrs;
|
||||
|
||||
auto a = v.attrs->get(state.ctx.symbols.create("derivation"));
|
||||
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.s.drvPath);
|
||||
if (a) {
|
||||
if (strict) state.forceValue(*a->value, a->pos);
|
||||
if (a->value->type() == nString)
|
||||
xmlAttrs["drvPath"] = drvPath = a->value->str();
|
||||
}
|
||||
|
||||
a = v.attrs->get(state.ctx.s.outPath);
|
||||
a = v.attrs()->get(state.ctx.s.outPath);
|
||||
if (a) {
|
||||
if (strict) state.forceValue(*a->value, a->pos);
|
||||
if (a->value->type() == nString) {
|
||||
@@ -106,14 +106,14 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||
XMLOpenElement _(doc, "derivation", xmlAttrs);
|
||||
|
||||
if (drvPath != "" && drvsSeen.insert(drvPath).second)
|
||||
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
|
||||
showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen);
|
||||
else
|
||||
doc.writeEmptyElement("repeated");
|
||||
}
|
||||
|
||||
else {
|
||||
XMLOpenElement _(doc, "attrs");
|
||||
showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen);
|
||||
showAttrs(state, strict, location, *v.attrs(), doc, context, drvsSeen);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -132,10 +132,10 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||
break;
|
||||
}
|
||||
XMLAttrs xmlAttrs;
|
||||
if (location) posToXML(state, xmlAttrs, state.ctx.positions[v.lambda.fun->pos]);
|
||||
if (location) posToXML(state, xmlAttrs, state.ctx.positions[v.lambda().fun->pos]);
|
||||
XMLOpenElement _(doc, "function", xmlAttrs);
|
||||
|
||||
if (auto formals = dynamic_cast<AttrsPattern *>(v.lambda.fun->pattern.get()); formals) {
|
||||
if (auto formals = dynamic_cast<AttrsPattern *>(v.lambda().fun->pattern.get()); formals) {
|
||||
XMLAttrs attrs;
|
||||
if (formals->name) attrs["name"] = state.ctx.symbols[formals->name];
|
||||
if (formals->ellipsis) attrs["ellipsis"] = "1";
|
||||
@@ -143,17 +143,17 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
|
||||
for (const AttrsPattern::Formal & i : formals->lexicographicOrder(state.ctx.symbols))
|
||||
doc.writeEmptyElement("attr", singletonAttrs("name", state.ctx.symbols[i.name]));
|
||||
} else
|
||||
doc.writeEmptyElement("varpat", singletonAttrs("name", state.ctx.symbols[v.lambda.fun->pattern->name]));
|
||||
doc.writeEmptyElement("varpat", singletonAttrs("name", state.ctx.symbols[v.lambda().fun->pattern->name]));
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case nExternal:
|
||||
v.external->printValueAsXML(state, strict, location, doc, context, drvsSeen, pos);
|
||||
v.external()->printValueAsXML(state, strict, location, doc, context, drvsSeen, pos);
|
||||
break;
|
||||
|
||||
case nFloat:
|
||||
doc.writeEmptyElement("float", singletonAttrs("value", fmt("%1%", v.fpoint)));
|
||||
doc.writeEmptyElement("float", singletonAttrs("value", fmt("%1%", v.fpoint())));
|
||||
break;
|
||||
|
||||
case nThunk:
|
||||
|
||||
+12
-12
@@ -15,16 +15,16 @@ static void copyContextToValue(Value & v, const NixStringContext & context)
|
||||
{
|
||||
if (!context.empty()) {
|
||||
size_t n = 0;
|
||||
v.string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
v._string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
for (auto & i : context)
|
||||
v.string.context[n++] = gcCopyStringIfNeeded(i.to_string());
|
||||
v.string.context[n] = 0;
|
||||
v._string.context[n++] = gcCopyStringIfNeeded(i.to_string());
|
||||
v._string.context[n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Value::Value(primop_t, PrimOp & primop)
|
||||
: internalType(tPrimOp)
|
||||
, primOp(&primop)
|
||||
, _primOp(&primop)
|
||||
, _primop_pad(0)
|
||||
{
|
||||
}
|
||||
@@ -41,29 +41,29 @@ bool Value::isTrivial() const
|
||||
internalType != tApp
|
||||
&& internalType != tPrimOpApp
|
||||
&& (internalType != tThunk
|
||||
|| (thunk.expr->try_cast<ExprSet>()
|
||||
&& static_cast<ExprSet *>(thunk.expr)->dynamicAttrs.empty())
|
||||
|| thunk.expr->try_cast<ExprLambda>()
|
||||
|| thunk.expr->try_cast<ExprList>());
|
||||
|| (thunk().expr->try_cast<ExprSet>()
|
||||
&& static_cast<ExprSet *>(thunk().expr)->dynamicAttrs.empty())
|
||||
|| thunk().expr->try_cast<ExprLambda>()
|
||||
|| thunk().expr->try_cast<ExprList>());
|
||||
}
|
||||
|
||||
PrimOp * Value::primOpAppPrimOp() const
|
||||
{
|
||||
Value * left = primOpApp.left;
|
||||
Value * left = primOpApp().left;
|
||||
while (left && !left->isPrimOp()) {
|
||||
left = left->primOpApp.left;
|
||||
left = left->primOpApp().left;
|
||||
}
|
||||
|
||||
if (!left)
|
||||
return nullptr;
|
||||
return left->primOp;
|
||||
return left->primOp();
|
||||
}
|
||||
|
||||
void Value::mkPrimOp(PrimOp * p)
|
||||
{
|
||||
clearValue();
|
||||
internalType = tPrimOp;
|
||||
primOp = p;
|
||||
_primOp = p;
|
||||
}
|
||||
|
||||
void Value::mkString(std::string_view s)
|
||||
|
||||
+123
-72
@@ -256,24 +256,20 @@ public:
|
||||
// we're not allowed to have it as an anonymous aggreagte member. we do
|
||||
// however still have the option to clear the data members using _empty
|
||||
// and leaving the second word of data cleared by setting only integer.
|
||||
integer = i;
|
||||
_integer = i;
|
||||
}
|
||||
|
||||
/// Constructs a nix language value of type "float", with the floating
|
||||
/// point value of @ref f.
|
||||
Value(floating_t, NixFloat f)
|
||||
: internalType(tFloat)
|
||||
, fpoint(f)
|
||||
, _fpoint(f)
|
||||
, _float_pad(0)
|
||||
{ }
|
||||
|
||||
/// Constructs a nix language value of type "bool", with the boolean
|
||||
/// value of @ref b.
|
||||
Value(boolean_t, bool b)
|
||||
: internalType(tBool)
|
||||
, boolean(b)
|
||||
, _bool_pad(0)
|
||||
{ }
|
||||
Value(boolean_t, bool b) : internalType(tBool), _boolean(b), _bool_pad(0) {}
|
||||
|
||||
/// Constructs a nix language value of type "string", with the value of the
|
||||
/// C-string pointed to by @ref strPtr, and optionally with an array of
|
||||
@@ -284,7 +280,7 @@ public:
|
||||
/// enabled), and string and context data copied into that memory.
|
||||
Value(string_t, char const * strPtr, char const ** contextPtr = nullptr)
|
||||
: internalType(tString)
|
||||
, string({.content = strPtr, .context = contextPtr})
|
||||
, _string({.content = strPtr, .context = contextPtr})
|
||||
{ }
|
||||
|
||||
/// Constructx a nix language value of type "string", with a copy of the
|
||||
@@ -294,7 +290,7 @@ public:
|
||||
/// performs a dynamic (GC) allocation to do so.
|
||||
Value(string_t, std::string_view copyFrom, NixStringContext const & context = {})
|
||||
: internalType(tString)
|
||||
, string({.content = gcCopyStringIfNeeded(copyFrom), .context = nullptr})
|
||||
, _string({.content = gcCopyStringIfNeeded(copyFrom), .context = nullptr})
|
||||
{
|
||||
if (context.empty()) {
|
||||
// It stays nullptr.
|
||||
@@ -302,16 +298,16 @@ public:
|
||||
}
|
||||
|
||||
// Copy the context.
|
||||
this->string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
this->_string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
|
||||
size_t n = 0;
|
||||
for (NixStringContextElem const & contextElem : context) {
|
||||
this->string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
|
||||
this->_string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
|
||||
n += 1;
|
||||
}
|
||||
|
||||
// Terminator sentinel.
|
||||
this->string.context[n] = nullptr;
|
||||
this->_string.context[n] = nullptr;
|
||||
}
|
||||
|
||||
/// Constructx a nix language value of type "string", with the value of the
|
||||
@@ -325,7 +321,7 @@ public:
|
||||
/// to do so.
|
||||
Value(string_t, char const * strPtr, NixStringContext const & context)
|
||||
: internalType(tString)
|
||||
, string({.content = strPtr, .context = nullptr})
|
||||
, _string({.content = strPtr, .context = nullptr})
|
||||
{
|
||||
if (context.empty()) {
|
||||
// It stays nullptr
|
||||
@@ -333,16 +329,16 @@ public:
|
||||
}
|
||||
|
||||
// Copy the context.
|
||||
this->string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
this->_string.context = gcAllocType<char const *>(context.size() + 1);
|
||||
|
||||
size_t n = 0;
|
||||
for (NixStringContextElem const & contextElem : context) {
|
||||
this->string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
|
||||
this->_string.context[n] = gcCopyStringIfNeeded(contextElem.to_string());
|
||||
n += 1;
|
||||
}
|
||||
|
||||
// Terminator sentinel.
|
||||
this->string.context[n] = nullptr;
|
||||
this->_string.context[n] = nullptr;
|
||||
}
|
||||
|
||||
/// Constructs a nix language value of type "path", with the value of the
|
||||
@@ -384,16 +380,16 @@ public:
|
||||
{
|
||||
if (items.size() == 1) {
|
||||
this->internalType = tList1;
|
||||
this->smallList[0] = items[0];
|
||||
this->smallList[1] = nullptr;
|
||||
this->_smallList[0] = items[0];
|
||||
this->_smallList[1] = nullptr;
|
||||
} else if (items.size() == 2) {
|
||||
this->internalType = tList2;
|
||||
this->smallList[0] = items[0];
|
||||
this->smallList[1] = items[1];
|
||||
this->_smallList[0] = items[0];
|
||||
this->_smallList[1] = items[1];
|
||||
} else {
|
||||
this->internalType = tListN;
|
||||
this->bigList.size = items.size();
|
||||
this->bigList.elems = items.data();
|
||||
this->_bigList.size = items.size();
|
||||
this->_bigList.elems = items.data();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,21 +408,21 @@ public:
|
||||
{
|
||||
if (items.size() == 1) {
|
||||
this->internalType = tList1;
|
||||
this->smallList[0] = transformer(*items.begin());
|
||||
this->smallList[1] = nullptr;
|
||||
this->_smallList[0] = transformer(*items.begin());
|
||||
this->_smallList[1] = nullptr;
|
||||
} else if (items.size() == 2) {
|
||||
this->internalType = tList2;
|
||||
auto it = items.begin();
|
||||
this->smallList[0] = transformer(*it);
|
||||
this->_smallList[0] = transformer(*it);
|
||||
it++;
|
||||
this->smallList[1] = transformer(*it);
|
||||
this->_smallList[1] = transformer(*it);
|
||||
} else {
|
||||
this->internalType = tListN;
|
||||
this->bigList.size = items.size();
|
||||
this->bigList.elems = gcAllocType<Value *>(items.size());
|
||||
this->_bigList.size = items.size();
|
||||
this->_bigList.elems = gcAllocType<Value *>(items.size());
|
||||
auto it = items.begin();
|
||||
for (size_t i = 0; i < items.size(); i++, it++) {
|
||||
this->bigList.elems[i] = transformer(*it);
|
||||
this->_bigList.elems[i] = transformer(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,7 +440,7 @@ public:
|
||||
/// has already been suitably allocated by something like nix::buildBindings.
|
||||
Value(attrs_t, Bindings * bindings)
|
||||
: internalType(tAttrs)
|
||||
, attrs(bindings)
|
||||
, _attrs(bindings)
|
||||
, _attrs_pad(0)
|
||||
{ }
|
||||
|
||||
@@ -454,7 +450,7 @@ public:
|
||||
/// the expression that will need to be evaluated @ref expr.
|
||||
Value(thunk_t, Env & env, Expr & expr)
|
||||
: internalType(tThunk)
|
||||
, thunk({ .env = &env, .expr = &expr })
|
||||
, _thunk({ .env = &env, .expr = &expr })
|
||||
{ }
|
||||
|
||||
/// Constructs a nix language value of type "lambda", which represents
|
||||
@@ -466,21 +462,21 @@ public:
|
||||
/// partially applied primop.
|
||||
Value(primOpApp_t, Value & lhs, Value & rhs)
|
||||
: internalType(tPrimOpApp)
|
||||
, primOpApp({ .left = &lhs, .right = &rhs })
|
||||
, _primOpApp({ .left = &lhs, .right = &rhs })
|
||||
{ }
|
||||
|
||||
/// Constructs a nix language value of type "lambda", which represents a
|
||||
/// lazy partial application of another lambda.
|
||||
Value(app_t, Value & lhs, Value & rhs)
|
||||
: internalType(tApp)
|
||||
, app({ .left = &lhs, .right = &rhs })
|
||||
, _app({ .left = &lhs, .right = &rhs })
|
||||
{ }
|
||||
|
||||
/// Constructs a nix language value of type "external", which is only used
|
||||
/// by plugins. Do any existing plugins even use this mechanism?
|
||||
Value(external_t, ExternalValueBase & external)
|
||||
: internalType(tExternal)
|
||||
, external(&external)
|
||||
, _external(&external)
|
||||
, _external_pad(0)
|
||||
{ }
|
||||
|
||||
@@ -492,13 +488,13 @@ public:
|
||||
/// until it is applied.
|
||||
Value(lambda_t, Env & env, ExprLambda & lambda)
|
||||
: internalType(tLambda)
|
||||
, lambda({ .env = &env, .fun = &lambda })
|
||||
, _lambda({ .env = &env, .fun = &lambda })
|
||||
{ }
|
||||
|
||||
/// Constructs an evil thunk, whose evaluation represents infinite recursion.
|
||||
explicit Value(blackhole_t)
|
||||
: internalType(tThunk)
|
||||
, thunk({ .env = nullptr, .expr = eBlackHoleAddr })
|
||||
, _thunk({ .env = nullptr, .expr = eBlackHoleAddr })
|
||||
{ }
|
||||
|
||||
Value(Value const & rhs) = default;
|
||||
@@ -540,7 +536,7 @@ public:
|
||||
inline bool isApp() const { return internalType == tApp; };
|
||||
inline bool isBlackhole() const
|
||||
{
|
||||
return internalType == tThunk && thunk.expr == eBlackHoleAddr;
|
||||
return internalType == tThunk && _thunk.expr == eBlackHoleAddr;
|
||||
}
|
||||
|
||||
// type() == nFunction
|
||||
@@ -554,9 +550,9 @@ public:
|
||||
/// to set the union's memory to zeroed memory.
|
||||
uintptr_t _empty[2];
|
||||
|
||||
NixInt integer;
|
||||
NixInt _integer;
|
||||
struct {
|
||||
bool boolean;
|
||||
bool _boolean;
|
||||
uintptr_t _bool_pad;
|
||||
};
|
||||
|
||||
@@ -585,45 +581,45 @@ public:
|
||||
struct {
|
||||
const char * content;
|
||||
const char * * context; // must be in sorted order
|
||||
} string;
|
||||
} _string;
|
||||
|
||||
struct {
|
||||
const char * _path;
|
||||
uintptr_t _path_pad;
|
||||
};
|
||||
struct {
|
||||
Bindings * attrs;
|
||||
Bindings * _attrs;
|
||||
uintptr_t _attrs_pad;
|
||||
};
|
||||
struct {
|
||||
size_t size;
|
||||
Value * * elems;
|
||||
} bigList;
|
||||
Value * smallList[2];
|
||||
} _bigList;
|
||||
Value * _smallList[2];
|
||||
struct {
|
||||
Env * env;
|
||||
Expr * expr;
|
||||
} thunk;
|
||||
} _thunk;
|
||||
struct {
|
||||
Value * left, * right;
|
||||
} app;
|
||||
} _app;
|
||||
struct {
|
||||
Env * env;
|
||||
ExprLambda * fun;
|
||||
} lambda;
|
||||
} _lambda;
|
||||
struct {
|
||||
PrimOp * primOp;
|
||||
PrimOp * _primOp;
|
||||
uintptr_t _primop_pad;
|
||||
};
|
||||
struct {
|
||||
Value * left, * right;
|
||||
} primOpApp;
|
||||
} _primOpApp;
|
||||
struct {
|
||||
ExternalValueBase * external;
|
||||
ExternalValueBase * _external;
|
||||
uintptr_t _external_pad;
|
||||
};
|
||||
struct {
|
||||
NixFloat fpoint;
|
||||
NixFloat _fpoint;
|
||||
uintptr_t _float_pad;
|
||||
};
|
||||
};
|
||||
@@ -662,7 +658,7 @@ public:
|
||||
*/
|
||||
inline void clearValue()
|
||||
{
|
||||
app.left = app.right = 0;
|
||||
_app.left = _app.right = 0;
|
||||
}
|
||||
|
||||
inline void mkInt(NixInt::Inner n)
|
||||
@@ -674,21 +670,21 @@ public:
|
||||
{
|
||||
clearValue();
|
||||
internalType = tInt;
|
||||
integer = n;
|
||||
_integer = n;
|
||||
}
|
||||
|
||||
inline void mkBool(bool b)
|
||||
{
|
||||
clearValue();
|
||||
internalType = tBool;
|
||||
boolean = b;
|
||||
_boolean = b;
|
||||
}
|
||||
|
||||
inline void mkString(const char * s, const char * * context = 0)
|
||||
{
|
||||
internalType = tString;
|
||||
string.content = s;
|
||||
string.context = context;
|
||||
_string.content = s;
|
||||
_string.context = context;
|
||||
}
|
||||
|
||||
void mkString(std::string_view s);
|
||||
@@ -716,7 +712,7 @@ public:
|
||||
{
|
||||
clearValue();
|
||||
internalType = tAttrs;
|
||||
attrs = a;
|
||||
_attrs = a;
|
||||
}
|
||||
|
||||
Value & mkAttrs(BindingsBuilder & bindings);
|
||||
@@ -730,35 +726,35 @@ public:
|
||||
internalType = tList2;
|
||||
else {
|
||||
internalType = tListN;
|
||||
bigList.size = size;
|
||||
_bigList.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
inline void mkThunk(Env * e, Expr & ex)
|
||||
{
|
||||
internalType = tThunk;
|
||||
thunk.env = e;
|
||||
thunk.expr = &ex;
|
||||
_thunk.env = e;
|
||||
_thunk.expr = &ex;
|
||||
}
|
||||
|
||||
inline void mkApp(Value * l, Value * r)
|
||||
{
|
||||
internalType = tApp;
|
||||
app.left = l;
|
||||
app.right = r;
|
||||
_app.left = l;
|
||||
_app.right = r;
|
||||
}
|
||||
|
||||
inline void mkLambda(Env * e, ExprLambda * f)
|
||||
{
|
||||
internalType = tLambda;
|
||||
lambda.env = e;
|
||||
lambda.fun = f;
|
||||
_lambda.env = e;
|
||||
_lambda.fun = f;
|
||||
}
|
||||
|
||||
inline void mkBlackhole()
|
||||
{
|
||||
internalType = tThunk;
|
||||
thunk.expr = eBlackHoleAddr;
|
||||
_thunk.expr = eBlackHoleAddr;
|
||||
}
|
||||
|
||||
void mkPrimOp(PrimOp * p);
|
||||
@@ -766,8 +762,8 @@ public:
|
||||
inline void mkPrimOpApp(Value * l, Value * r)
|
||||
{
|
||||
internalType = tPrimOpApp;
|
||||
primOpApp.left = l;
|
||||
primOpApp.right = r;
|
||||
_primOpApp.left = l;
|
||||
_primOpApp.right = r;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,14 +775,14 @@ public:
|
||||
{
|
||||
clearValue();
|
||||
internalType = tExternal;
|
||||
external = e;
|
||||
_external = e;
|
||||
}
|
||||
|
||||
inline void mkFloat(NixFloat n)
|
||||
{
|
||||
clearValue();
|
||||
internalType = tFloat;
|
||||
fpoint = n;
|
||||
_fpoint = n;
|
||||
}
|
||||
|
||||
bool isList() const
|
||||
@@ -796,17 +792,17 @@ public:
|
||||
|
||||
Value * * listElems()
|
||||
{
|
||||
return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
|
||||
return internalType == tList1 || internalType == tList2 ? _smallList : _bigList.elems;
|
||||
}
|
||||
|
||||
Value * const * listElems() const
|
||||
{
|
||||
return internalType == tList1 || internalType == tList2 ? smallList : bigList.elems;
|
||||
return internalType == tList1 || internalType == tList2 ? _smallList : _bigList.elems;
|
||||
}
|
||||
|
||||
size_t listSize() const
|
||||
{
|
||||
return internalType == tList1 ? 1 : internalType == tList2 ? 2 : bigList.size;
|
||||
return internalType == tList1 ? 1 : internalType == tList2 ? 2 : _bigList.size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -853,7 +849,62 @@ public:
|
||||
std::string_view str() const
|
||||
{
|
||||
assert(internalType == tString);
|
||||
return std::string_view(string.content);
|
||||
return std::string_view(_string.content);
|
||||
}
|
||||
|
||||
NixInt integer() const
|
||||
{
|
||||
return _integer;
|
||||
}
|
||||
|
||||
bool boolean() const
|
||||
{
|
||||
return _boolean;
|
||||
}
|
||||
|
||||
const auto & string() const
|
||||
{
|
||||
return _string;
|
||||
}
|
||||
|
||||
auto attrs() const
|
||||
{
|
||||
return _attrs;
|
||||
}
|
||||
|
||||
const auto & thunk() const
|
||||
{
|
||||
return _thunk;
|
||||
}
|
||||
|
||||
const auto & app() const
|
||||
{
|
||||
return _app;
|
||||
}
|
||||
|
||||
const auto & lambda() const
|
||||
{
|
||||
return _lambda;
|
||||
}
|
||||
|
||||
PrimOp * primOp() const
|
||||
{
|
||||
return _primOp;
|
||||
}
|
||||
|
||||
const auto & primOpApp() const
|
||||
{
|
||||
return _primOpApp;
|
||||
}
|
||||
|
||||
ExternalValueBase * external() const
|
||||
{
|
||||
return _external;
|
||||
}
|
||||
|
||||
NixFloat fpoint() const
|
||||
{
|
||||
return _fpoint;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+3
-3
@@ -102,14 +102,14 @@ struct CmdBundle : InstallableCommand
|
||||
if (!evalState->isDerivation(*vRes))
|
||||
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->s.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->s.outPath);
|
||||
if (!attr2)
|
||||
throw Error("the bundler '%s' does not produce a derivation", bundler.what());
|
||||
|
||||
@@ -123,7 +123,7 @@ struct CmdBundle : InstallableCommand
|
||||
}));
|
||||
|
||||
if (!outLink) {
|
||||
auto * attr = vRes->attrs->get(evaluator->s.name);
|
||||
auto * attr = vRes->attrs()->get(evaluator->s.name);
|
||||
if (!attr)
|
||||
throw Error("attribute 'name' missing");
|
||||
outLink = evalState->forceStringNoCtx(*attr->value, attr->pos, "");
|
||||
|
||||
+25
-25
@@ -182,7 +182,7 @@ static void enumerateOutputs(
|
||||
{
|
||||
state.forceAttrs(vFlake, noPos, "while evaluating a flake to get its outputs");
|
||||
|
||||
auto aOutputs = vFlake.attrs->get(state.ctx.symbols.create("outputs"));
|
||||
auto aOutputs = vFlake.attrs()->get(state.ctx.symbols.create("outputs"));
|
||||
assert(aOutputs);
|
||||
|
||||
state.forceAttrs(*aOutputs->value, noPos, "while evaluating the outputs of a flake");
|
||||
@@ -192,10 +192,10 @@ static void enumerateOutputs(
|
||||
/* Hack: ensure that hydraJobs is evaluated before anything
|
||||
else. This way we can disable IFD for hydraJobs and then enable
|
||||
it for other outputs. */
|
||||
if (auto attr = aOutputs->value->attrs->get(sHydraJobs))
|
||||
if (auto attr = aOutputs->value->attrs()->get(sHydraJobs))
|
||||
callback(state.ctx.symbols[attr->name], *attr->value, attr->pos);
|
||||
|
||||
for (auto & attr : *aOutputs->value->attrs) {
|
||||
for (auto & attr : *aOutputs->value->attrs()) {
|
||||
if (attr.name != sHydraJobs)
|
||||
callback(state.ctx.symbols[attr.name], *attr.value, attr.pos);
|
||||
}
|
||||
@@ -463,7 +463,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
if (!v.isLambda()) {
|
||||
throw Error("overlay is not a function, but %s instead", showType(v));
|
||||
}
|
||||
auto body = v.lambda.fun->body->try_cast<ExprLambda>();
|
||||
auto body = v.lambda().fun->body->try_cast<ExprLambda>();
|
||||
if (!body)
|
||||
throw Error("overlay is not a function with two arguments, but only takes one");
|
||||
if (body->body->try_cast<ExprLambda>())
|
||||
@@ -499,7 +499,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
if (state->isDerivation(v))
|
||||
throw Error("jobset should not be a derivation at top-level");
|
||||
|
||||
for (auto & attr : *v.attrs) {
|
||||
for (auto & attr : *v.attrs()) {
|
||||
state->forceAttrs(*attr.value, attr.pos, "");
|
||||
auto attrPath2 = concatStrings(attrPath, ".", evaluator->symbols[attr.name]);
|
||||
if (state->isDerivation(*attr.value)) {
|
||||
@@ -538,7 +538,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
|
||||
state->forceAttrs(v, pos, "");
|
||||
|
||||
if (auto attr = v.attrs->get(evaluator->symbols.create("path"))) {
|
||||
if (auto attr = v.attrs()->get(evaluator->symbols.create("path"))) {
|
||||
if (attr->name == evaluator->symbols.create("path")) {
|
||||
NixStringContext context;
|
||||
auto path = state->ctx.paths.checkSourcePath(
|
||||
@@ -551,12 +551,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
} else
|
||||
throw Error("template '%s' lacks attribute 'path'", attrPath);
|
||||
|
||||
if (auto attr = v.attrs->get(evaluator->symbols.create("description")))
|
||||
if (auto attr = v.attrs()->get(evaluator->symbols.create("description")))
|
||||
state->forceStringNoCtx(*attr->value, attr->pos, "");
|
||||
else
|
||||
throw Error("template '%s' lacks attribute 'description'", attrPath);
|
||||
|
||||
for (auto & attr : *v.attrs) {
|
||||
for (auto & attr : *v.attrs()) {
|
||||
std::string_view name(evaluator->symbols[attr.name]);
|
||||
if (name != "path" && name != "description" && name != "welcomeText")
|
||||
throw Error("template '%s' has unsupported attribute '%s'", attrPath, name);
|
||||
@@ -617,12 +617,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
|
||||
if (name == "checks") {
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
state->forceAttrs(*attr.value, attr.pos, "");
|
||||
for (auto & attr2 : *attr.value->attrs) {
|
||||
for (auto & attr2 : *attr.value->attrs()) {
|
||||
auto drvPath = checkDerivation(
|
||||
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
|
||||
*attr2.value, attr2.pos);
|
||||
@@ -640,7 +640,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "formatter")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
@@ -654,12 +654,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "packages" || name == "devShells")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
state->forceAttrs(*attr.value, attr.pos, "");
|
||||
for (auto & attr2 : *attr.value->attrs)
|
||||
for (auto & attr2 : *attr.value->attrs())
|
||||
checkDerivation(
|
||||
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
|
||||
*attr2.value, attr2.pos);
|
||||
@@ -670,12 +670,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "apps")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
state->forceAttrs(*attr.value, attr.pos, "");
|
||||
for (auto & attr2 : *attr.value->attrs)
|
||||
for (auto & attr2 : *attr.value->attrs())
|
||||
checkApp(
|
||||
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
|
||||
*attr2.value, attr2.pos);
|
||||
@@ -686,7 +686,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "defaultPackage" || name == "devShell")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
@@ -700,7 +700,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "defaultApp")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos) ) {
|
||||
@@ -714,7 +714,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "legacyPackages")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
checkSystemName(evaluator->symbols[attr.name], attr.pos);
|
||||
checkSystemType(evaluator->symbols[attr.name], attr.pos);
|
||||
// FIXME: do getDerivations?
|
||||
@@ -729,7 +729,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "overlays")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs)
|
||||
for (auto & attr : *vOutput.attrs())
|
||||
checkOverlay(fmt("%s.%s", name, evaluator->symbols[attr.name]),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
@@ -742,7 +742,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "nixosModules")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs)
|
||||
for (auto & attr : *vOutput.attrs())
|
||||
checkModule(fmt("%s.%s", name, evaluator->symbols[attr.name]),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
@@ -750,7 +750,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "nixosConfigurations")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs)
|
||||
for (auto & attr : *vOutput.attrs())
|
||||
checkNixOSConfiguration(fmt("%s.%s", name, evaluator->symbols[attr.name]),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
@@ -768,7 +768,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "templates")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs)
|
||||
for (auto & attr : *vOutput.attrs())
|
||||
checkTemplate(fmt("%s.%s", name, evaluator->symbols[attr.name]),
|
||||
*attr.value, attr.pos);
|
||||
}
|
||||
@@ -776,7 +776,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "defaultBundler")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
@@ -790,12 +790,12 @@ struct CmdFlakeCheck : FlakeCommand
|
||||
else if (name == "bundlers")
|
||||
{
|
||||
state->forceAttrs(vOutput, pos, "");
|
||||
for (auto & attr : *vOutput.attrs) {
|
||||
for (auto & attr : *vOutput.attrs()) {
|
||||
const auto & attr_name = evaluator->symbols[attr.name];
|
||||
checkSystemName(attr_name, attr.pos);
|
||||
if (checkSystemType(attr_name, attr.pos)) {
|
||||
state->forceAttrs(*attr.value, attr.pos, "");
|
||||
for (auto & attr2 : *attr.value->attrs) {
|
||||
for (auto & attr2 : *attr.value->attrs()) {
|
||||
checkBundler(
|
||||
fmt("%s.%s.%s", name, attr_name, evaluator->symbols[attr2.name]),
|
||||
*attr2.value, attr2.pos);
|
||||
|
||||
+3
-3
@@ -369,7 +369,7 @@ static void showHelp(AsyncIoRoot & aio, std::vector<std::string> subcommand, Nix
|
||||
state->callFunction(*vGenerateManpage, evaluator.builtins.get("false"), *vRes, noPos);
|
||||
state->callFunction(*vRes, *vDump, *vRes, noPos);
|
||||
|
||||
auto attr = vRes->attrs->get(evaluator.symbols.create(mdName + ".md"));
|
||||
auto attr = vRes->attrs()->get(evaluator.symbols.create(mdName + ".md"));
|
||||
if (!attr)
|
||||
throw UsageError("`nix` has no subcommand '%s'", concatStringsSep("", subcommand));
|
||||
|
||||
@@ -523,11 +523,11 @@ void mainWrapped(AsyncIoRoot & aio, int argc, char * * argv)
|
||||
auto res = JSON::object();
|
||||
res["builtins"] = ({
|
||||
auto builtinsJson = JSON::object();
|
||||
auto builtins = state.builtins.env.values[0]->attrs;
|
||||
auto builtins = state.builtins.env.values[0]->attrs();
|
||||
for (auto & builtin : *builtins) {
|
||||
auto b = JSON::object();
|
||||
if (!builtin.value->isPrimOp()) continue;
|
||||
auto primOp = builtin.value->primOp;
|
||||
auto primOp = builtin.value->primOp();
|
||||
if (!primOp->doc) continue;
|
||||
b["arity"] = primOp->arity;
|
||||
b["args"] = primOp->args;
|
||||
|
||||
+4
-4
@@ -35,7 +35,7 @@ std::string resolveMirrorUrl(EvalState & state, const std::string & url)
|
||||
vMirrors);
|
||||
state.forceAttrs(vMirrors, noPos, "while evaluating the set of all mirrors");
|
||||
|
||||
auto mirrorList = vMirrors.attrs->get(state.ctx.symbols.create(mirrorName));
|
||||
auto mirrorList = vMirrors.attrs()->get(state.ctx.symbols.create(mirrorName));
|
||||
if (!mirrorList) {
|
||||
throw Error("unknown mirror name '%s'", mirrorName);
|
||||
}
|
||||
@@ -211,7 +211,7 @@ static int main_nix_prefetch_url(AsyncIoRoot & aio, std::string programName, Str
|
||||
state->forceAttrs(v, noPos, "while evaluating the source attribute to prefetch");
|
||||
|
||||
/* Extract the URL. */
|
||||
auto * attr = v.attrs->get(evaluator->symbols.create("urls"));
|
||||
auto * attr = v.attrs()->get(evaluator->symbols.create("urls"));
|
||||
if (!attr)
|
||||
throw Error("attribute 'urls' missing");
|
||||
state->forceList(*attr->value, noPos, "while evaluating the urls to prefetch");
|
||||
@@ -220,7 +220,7 @@ static int main_nix_prefetch_url(AsyncIoRoot & aio, std::string programName, Str
|
||||
url = state->forceString(*attr->value->listElems()[0], noPos, "while evaluating the first url from the urls list");
|
||||
|
||||
/* Extract the hash mode. */
|
||||
auto attr2 = v.attrs->get(evaluator->symbols.create("outputHashMode"));
|
||||
auto attr2 = v.attrs()->get(evaluator->symbols.create("outputHashMode"));
|
||||
if (!attr2)
|
||||
printInfo("warning: this does not look like a fetchurl call");
|
||||
else
|
||||
@@ -228,7 +228,7 @@ static int main_nix_prefetch_url(AsyncIoRoot & aio, std::string programName, Str
|
||||
|
||||
/* Extract the name. */
|
||||
if (!name) {
|
||||
auto attr3 = v.attrs->get(evaluator->symbols.create("name"));
|
||||
auto attr3 = v.attrs()->get(evaluator->symbols.create("name"));
|
||||
if (!attr3)
|
||||
name = state->forceString(*attr3->value, noPos, "while evaluating the name of the source to prefetch");
|
||||
}
|
||||
|
||||
@@ -78,13 +78,13 @@ static std::string attrPathJoin(nix::JSON input) {
|
||||
static std::optional<Constituents>
|
||||
readConstituents(const nix::Value *v, nix::box_ptr<nix::EvalState> &state,
|
||||
nix::ref<nix::eval_cache::CachingEvaluator> &evaluator) {
|
||||
auto a = v->attrs->get(state->ctx.symbols.create("_hydraAggregate"));
|
||||
auto a = v->attrs()->get(state->ctx.symbols.create("_hydraAggregate"));
|
||||
if (a && state->forceBool(*a->value, a->pos,
|
||||
"while evaluating the "
|
||||
"`_hydraAggregate` attribute")) {
|
||||
std::vector<std::string> constituents;
|
||||
std::vector<std::string> namedConstituents;
|
||||
auto a = v->attrs->get(state->ctx.symbols.create("constituents"));
|
||||
auto a = v->attrs()->get(state->ctx.symbols.create("constituents"));
|
||||
if (!a)
|
||||
state->ctx.errors
|
||||
.make<nix::EvalError>("derivation must have a ‘constituents’ "
|
||||
@@ -197,13 +197,13 @@ void worker(nix::ref<nix::eval_cache::CachingEvaluator> evaluator,
|
||||
// = true;` for top-level attrset
|
||||
|
||||
for (auto &i :
|
||||
v->attrs->lexicographicOrder(evaluator->symbols)) {
|
||||
v->attrs()->lexicographicOrder(evaluator->symbols)) {
|
||||
const std::string_view name = evaluator->symbols[i->name];
|
||||
attrs.emplace_back(name);
|
||||
|
||||
if (name == "recurseForDerivations" &&
|
||||
!args.forceRecurse) {
|
||||
auto attrv = v->attrs->get(
|
||||
auto attrv = v->attrs()->get(
|
||||
evaluator->s.recurseForDerivations);
|
||||
recurse = state->forceBool(
|
||||
*attrv->value, attrv->pos,
|
||||
|
||||
@@ -84,28 +84,28 @@ namespace nix {
|
||||
if (arg.type() != nInt) {
|
||||
return false;
|
||||
}
|
||||
return arg.integer.value == v;
|
||||
return arg.integer().value == v;
|
||||
}
|
||||
|
||||
MATCHER_P(IsFloatEq, v, fmt("The float is equal to \"%1%\"", v)) {
|
||||
if (arg.type() != nFloat) {
|
||||
return false;
|
||||
}
|
||||
return arg.fpoint == v;
|
||||
return arg.fpoint() == v;
|
||||
}
|
||||
|
||||
MATCHER(IsTrue, "") {
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean == true;
|
||||
return arg.boolean() == true;
|
||||
}
|
||||
|
||||
MATCHER(IsFalse, "") {
|
||||
if (arg.type() != nBool) {
|
||||
return false;
|
||||
}
|
||||
return arg.boolean == false;
|
||||
return arg.boolean() == false;
|
||||
}
|
||||
|
||||
MATCHER_P(IsPathEq, p, fmt("Is a path equal to \"%1%\"", p)) {
|
||||
@@ -136,8 +136,8 @@ namespace nix {
|
||||
if (arg.type() != nAttrs) {
|
||||
*result_listener << "Expected set got " << arg.type();
|
||||
return false;
|
||||
} else if (arg.attrs->size() != (size_t)n) {
|
||||
*result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs->size();
|
||||
} else if (arg.attrs()->size() != (size_t)n) {
|
||||
*result_listener << "Expected a set with " << n << " attributes but got " << arg.attrs()->size();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace nix {
|
||||
auto v = eval("builtins.tryEval (throw \"\")");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
auto s = createSymbol("success");
|
||||
auto p = v.attrs->get(s);
|
||||
auto p = v.attrs()->get(s);
|
||||
ASSERT_NE(p, nullptr);
|
||||
ASSERT_THAT(*p->value, IsFalse());
|
||||
}
|
||||
@@ -80,11 +80,11 @@ namespace nix {
|
||||
auto v = eval("builtins.tryEval 123");
|
||||
ASSERT_THAT(v, IsAttrs());
|
||||
auto s = createSymbol("success");
|
||||
auto p = v.attrs->get(s);
|
||||
auto p = v.attrs()->get(s);
|
||||
ASSERT_NE(p, nullptr);
|
||||
ASSERT_THAT(*p->value, IsTrue());
|
||||
s = createSymbol("value");
|
||||
p = v.attrs->get(s);
|
||||
p = v.attrs()->get(s);
|
||||
ASSERT_NE(p, nullptr);
|
||||
ASSERT_THAT(*p->value, IsIntEq(123));
|
||||
}
|
||||
@@ -184,14 +184,14 @@ namespace nix {
|
||||
TEST_F(PrimOpTest, removeAttrsRetains) {
|
||||
auto v = eval("builtins.removeAttrs { x = 1; y = 2; } [\"x\"]");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
ASSERT_NE(v.attrs->get(createSymbol("y")), nullptr);
|
||||
ASSERT_NE(v.attrs()->get(createSymbol("y")), nullptr);
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, listToAttrsEmptyList) {
|
||||
auto v = eval("builtins.listToAttrs []");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(0));
|
||||
ASSERT_EQ(v.type(), nAttrs);
|
||||
ASSERT_EQ(v.attrs->size(), 0);
|
||||
ASSERT_EQ(v.attrs()->size(), 0);
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, listToAttrsNotFieldName) {
|
||||
@@ -201,7 +201,7 @@ namespace nix {
|
||||
TEST_F(PrimOpTest, listToAttrs) {
|
||||
auto v = eval("builtins.listToAttrs [ { name = \"key\"; value = 123; } ]");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto key = v.attrs->get(createSymbol("key"));
|
||||
auto key = v.attrs()->get(createSymbol("key"));
|
||||
ASSERT_NE(key, nullptr);
|
||||
ASSERT_THAT(*key->value, IsIntEq(123));
|
||||
}
|
||||
@@ -209,7 +209,7 @@ namespace nix {
|
||||
TEST_F(PrimOpTest, intersectAttrs) {
|
||||
auto v = eval("builtins.intersectAttrs { a = 1; b = 2; } { b = 3; c = 4; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto b = v.attrs->get(createSymbol("b"));
|
||||
auto b = v.attrs()->get(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(3));
|
||||
}
|
||||
@@ -225,11 +225,11 @@ namespace nix {
|
||||
auto v = eval("builtins.functionArgs ({ x, y ? 123}: 1)");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
|
||||
auto x = v.attrs->get(createSymbol("x"));
|
||||
auto x = v.attrs()->get(createSymbol("x"));
|
||||
ASSERT_NE(x, nullptr);
|
||||
ASSERT_THAT(*x->value, IsFalse());
|
||||
|
||||
auto y = v.attrs->get(createSymbol("y"));
|
||||
auto y = v.attrs()->get(createSymbol("y"));
|
||||
ASSERT_NE(y, nullptr);
|
||||
ASSERT_THAT(*y->value, IsTrue());
|
||||
}
|
||||
@@ -238,13 +238,13 @@ namespace nix {
|
||||
auto v = eval("builtins.mapAttrs (name: value: value * 10) { a = 1; b = 2; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
|
||||
auto a = v.attrs->get(createSymbol("a"));
|
||||
auto a = v.attrs()->get(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
ASSERT_THAT(*a->value, IsThunk());
|
||||
state.forceValue(*a->value, noPos);
|
||||
ASSERT_THAT(*a->value, IsIntEq(10));
|
||||
|
||||
auto b = v.attrs->get(createSymbol("b"));
|
||||
auto b = v.attrs()->get(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsThunk());
|
||||
state.forceValue(*b->value, noPos);
|
||||
@@ -393,13 +393,13 @@ namespace nix {
|
||||
auto v = eval("builtins.partition (x: x > 10) [1 23 9 3 42]");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
|
||||
auto right = v.attrs->get(createSymbol("right"));
|
||||
auto right = v.attrs()->get(createSymbol("right"));
|
||||
ASSERT_NE(right, nullptr);
|
||||
ASSERT_THAT(*right->value, IsListOfSize(2));
|
||||
ASSERT_THAT(*right->value->listElems()[0], IsIntEq(23));
|
||||
ASSERT_THAT(*right->value->listElems()[1], IsIntEq(42));
|
||||
|
||||
auto wrong = v.attrs->get(createSymbol("wrong"));
|
||||
auto wrong = v.attrs()->get(createSymbol("wrong"));
|
||||
ASSERT_NE(wrong, nullptr);
|
||||
ASSERT_EQ(wrong->value->type(), nList);
|
||||
ASSERT_EQ(wrong->value->listSize(), 3);
|
||||
@@ -636,14 +636,14 @@ namespace nix {
|
||||
auto v = eval("derivation");
|
||||
ASSERT_EQ(v.type(), nFunction);
|
||||
ASSERT_TRUE(v.isLambda());
|
||||
ASSERT_NE(v.lambda.fun, nullptr);
|
||||
ASSERT_TRUE(dynamic_cast<AttrsPattern *>(v.lambda.fun->pattern.get()));
|
||||
ASSERT_NE(v.lambda().fun, nullptr);
|
||||
ASSERT_TRUE(dynamic_cast<AttrsPattern *>(v.lambda().fun->pattern.get()));
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, currentTime) {
|
||||
auto v = eval("builtins.currentTime");
|
||||
ASSERT_EQ(v.type(), nInt);
|
||||
ASSERT_TRUE(v.integer > 0);
|
||||
ASSERT_TRUE(v.integer() > 0);
|
||||
}
|
||||
|
||||
TEST_F(PrimOpTest, splitVersion) {
|
||||
@@ -704,11 +704,11 @@ namespace nix {
|
||||
auto v = eval(expr);
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
|
||||
auto name = v.attrs->get(createSymbol("name"));
|
||||
auto name = v.attrs()->get(createSymbol("name"));
|
||||
ASSERT_TRUE(name);
|
||||
ASSERT_THAT(*name->value, IsStringEq(expectedName));
|
||||
|
||||
auto version = v.attrs->get(createSymbol("version"));
|
||||
auto version = v.attrs()->get(createSymbol("version"));
|
||||
ASSERT_TRUE(version);
|
||||
ASSERT_THAT(*version->value, IsStringEq(expectedVersion));
|
||||
}
|
||||
|
||||
@@ -67,11 +67,11 @@ namespace nix {
|
||||
TEST_F(TrivialExpressionTest, updateAttrs) {
|
||||
auto v = eval("{ a = 1; } // { b = 2; a = 3; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||
auto a = v.attrs->get(createSymbol("a"));
|
||||
auto a = v.attrs()->get(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
ASSERT_THAT(*a->value, IsIntEq(3));
|
||||
|
||||
auto b = v.attrs->get(createSymbol("b"));
|
||||
auto b = v.attrs()->get(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(2));
|
||||
}
|
||||
@@ -168,7 +168,7 @@ namespace nix {
|
||||
auto v = eval(expr);
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
|
||||
auto a = v.attrs->get(createSymbol("a"));
|
||||
auto a = v.attrs()->get(createSymbol("a"));
|
||||
ASSERT_NE(a, nullptr);
|
||||
|
||||
ASSERT_THAT(*a->value, IsThunk());
|
||||
@@ -176,11 +176,11 @@ namespace nix {
|
||||
|
||||
ASSERT_THAT(*a->value, IsAttrsOfSize(2));
|
||||
|
||||
auto b = a->value->attrs->get(createSymbol("b"));
|
||||
auto b = a->value->attrs()->get(createSymbol("b"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
|
||||
auto c = a->value->attrs->get(createSymbol("c"));
|
||||
auto c = a->value->attrs()->get(createSymbol("c"));
|
||||
ASSERT_NE(c, nullptr);
|
||||
ASSERT_THAT(*c->value, IsIntEq(2));
|
||||
}
|
||||
@@ -202,7 +202,7 @@ namespace nix {
|
||||
TEST_F(TrivialExpressionTest, bindOr) {
|
||||
auto v = eval("{ or = 1; }");
|
||||
ASSERT_THAT(v, IsAttrsOfSize(1));
|
||||
auto b = v.attrs->get(createSymbol("or"));
|
||||
auto b = v.attrs()->get(createSymbol("or"));
|
||||
ASSERT_NE(b, nullptr);
|
||||
ASSERT_THAT(*b->value, IsIntEq(1));
|
||||
}
|
||||
|
||||
@@ -83,9 +83,9 @@ TEST_F(ValuePrintingTests, tList)
|
||||
vTwo.mkInt(2);
|
||||
|
||||
Value vList = evaluator.mem.newList(5);
|
||||
vList.bigList.elems[0] = &vOne;
|
||||
vList.bigList.elems[1] = &vTwo;
|
||||
vList.bigList.size = 3;
|
||||
vList._bigList.elems[0] = &vOne;
|
||||
vList._bigList.elems[1] = &vTwo;
|
||||
vList._bigList.size = 3;
|
||||
|
||||
test(vList, "[ 1 2 «nullptr» ]");
|
||||
}
|
||||
@@ -261,10 +261,10 @@ TEST_F(ValuePrintingTests, depthList)
|
||||
vNested.mkAttrs(builder2.finish());
|
||||
|
||||
Value vList = evaluator.mem.newList(5);
|
||||
vList.bigList.elems[0] = &vOne;
|
||||
vList.bigList.elems[1] = &vTwo;
|
||||
vList.bigList.elems[2] = &vNested;
|
||||
vList.bigList.size = 3;
|
||||
vList._bigList.elems[0] = &vOne;
|
||||
vList._bigList.elems[1] = &vTwo;
|
||||
vList._bigList.elems[2] = &vNested;
|
||||
vList._bigList.size = 3;
|
||||
|
||||
test(vList, "[ 1 2 { ... } ]", PrintOptions { .maxDepth = 1 });
|
||||
test(vList, "[ 1 2 { nested = { ... }; one = 1; two = 2; } ]", PrintOptions { .maxDepth = 2 });
|
||||
@@ -466,7 +466,7 @@ TEST_F(ValuePrintingTests, ansiColorsError)
|
||||
auto & e = evaluator.parseExprFromString("{ a = throw \"uh oh!\"; }", {CanonPath::root});
|
||||
state.eval(e, vError);
|
||||
|
||||
test(*vError.attrs->begin()->value,
|
||||
test(*vError.attrs()->begin()->value,
|
||||
ANSI_RED
|
||||
"«error: uh oh!»"
|
||||
ANSI_NORMAL,
|
||||
@@ -517,7 +517,7 @@ TEST_F(ValuePrintingTests, ansiColorsAssert)
|
||||
state.eval(e, v);
|
||||
|
||||
ASSERT_EQ(v.type(), nAttrs);
|
||||
test(*v.attrs->begin()->value,
|
||||
test(*v.attrs()->begin()->value,
|
||||
ANSI_RED "«error: assertion failed»" ANSI_NORMAL,
|
||||
PrintOptions {
|
||||
.ansiColors = true,
|
||||
@@ -534,9 +534,9 @@ TEST_F(ValuePrintingTests, ansiColorsList)
|
||||
vTwo.mkInt(2);
|
||||
|
||||
Value vList = evaluator.mem.newList(5);
|
||||
vList.bigList.elems[0] = &vOne;
|
||||
vList.bigList.elems[1] = &vTwo;
|
||||
vList.bigList.size = 3;
|
||||
vList._bigList.elems[0] = &vOne;
|
||||
vList._bigList.elems[1] = &vTwo;
|
||||
vList._bigList.size = 3;
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_CYAN "2" ANSI_NORMAL " " ANSI_MAGENTA "«nullptr»" ANSI_NORMAL " ]",
|
||||
@@ -672,9 +672,9 @@ TEST_F(ValuePrintingTests, ansiColorsListRepeated)
|
||||
vInner.mkAttrs(innerBuilder.finish());
|
||||
|
||||
Value vList = evaluator.mem.newList(3);
|
||||
vList.bigList.elems[0] = &vInner;
|
||||
vList.bigList.elems[1] = &vInner;
|
||||
vList.bigList.size = 2;
|
||||
vList._bigList.elems[0] = &vInner;
|
||||
vList._bigList.elems[1] = &vInner;
|
||||
vList._bigList.size = 2;
|
||||
|
||||
test(vList,
|
||||
"[ { x = " ANSI_CYAN "0" ANSI_NORMAL "; } " ANSI_MAGENTA "«repeated»" ANSI_NORMAL " ]",
|
||||
@@ -695,9 +695,9 @@ TEST_F(ValuePrintingTests, listRepeated)
|
||||
vInner.mkAttrs(innerBuilder.finish());
|
||||
|
||||
Value vList = evaluator.mem.newList(3);
|
||||
vList.bigList.elems[0] = &vInner;
|
||||
vList.bigList.elems[1] = &vInner;
|
||||
vList.bigList.size = 2;
|
||||
vList._bigList.elems[0] = &vInner;
|
||||
vList._bigList.elems[1] = &vInner;
|
||||
vList._bigList.size = 2;
|
||||
|
||||
test(vList, "[ { x = 0; } «repeated» ]", PrintOptions { });
|
||||
test(vList,
|
||||
@@ -752,9 +752,9 @@ TEST_F(ValuePrintingTests, ansiColorsListElided)
|
||||
vTwo.mkInt(2);
|
||||
|
||||
Value vList = evaluator.mem.newList(4);
|
||||
vList.bigList.elems[0] = &vOne;
|
||||
vList.bigList.elems[1] = &vTwo;
|
||||
vList.bigList.size = 2;
|
||||
vList._bigList.elems[0] = &vOne;
|
||||
vList._bigList.elems[1] = &vTwo;
|
||||
vList._bigList.size = 2;
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«1 item elided»" ANSI_NORMAL " ]",
|
||||
@@ -766,8 +766,8 @@ TEST_F(ValuePrintingTests, ansiColorsListElided)
|
||||
Value vThree;
|
||||
vThree.mkInt(3);
|
||||
|
||||
vList.bigList.elems[2] = &vThree;
|
||||
vList.bigList.size = 3;
|
||||
vList._bigList.elems[2] = &vThree;
|
||||
vList._bigList.size = 3;
|
||||
|
||||
test(vList,
|
||||
"[ " ANSI_CYAN "1" ANSI_NORMAL " " ANSI_FAINT "«2 items elided»" ANSI_NORMAL " ]",
|
||||
|
||||
Reference in New Issue
Block a user