diff --git a/lix/legacy/nix-build.cc b/lix/legacy/nix-build.cc index d9ab74931..517ee8df2 100644 --- a/lix/legacy/nix-build.cc +++ b/lix/legacy/nix-build.cc @@ -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(v.lambda.fun->pattern.get())) { + if (auto pattern = dynamic_cast(v.lambda().fun->pattern.get())) { for (auto & i : pattern->formals) { if (evaluator->symbols[i.name] == "inNixShell") { add = true; diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index 477b7a156..9f17f3457 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -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; diff --git a/lix/legacy/user-env.cc b/lix/legacy/user-env.cc index 5466244bb..94590789f 100644 --- a/lix/legacy/user-env.cc +++ b/lix/legacy/user-env.cc @@ -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. */ diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index 0bc8c60cd..3db81e12a 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -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 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; diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index 7b3012287..242093e14 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -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(&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(&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(replInit->lambda.fun->pattern.get()); attrs && !attrs->ellipsis) { + if (auto attrs = dynamic_cast(replInit->lambda().fun->pattern.get()); attrs && !attrs->ellipsis) { evaluator.errors.make( "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; } ); } diff --git a/lix/libexpr/attr-path.cc b/lix/libexpr/attr-path.cc index a255e701a..813b5ca57 100644 --- a/lix/libexpr/attr-path.cc +++ b/lix/libexpr/attr-path.cc @@ -111,10 +111,10 @@ std::pair 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 attrNames; - for (auto & attr : *v->attrs) + for (auto & attr : *v->attrs()) attrNames.emplace(state.ctx.symbols[attr.name]); auto suggestions = Suggestions::bestMatches(attrNames, attr); diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index afce5633c..2da23d303 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -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(&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::maybeGetAttr(EvalState & state, const st return nullptr; //errors.make("'%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("'%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("'%s' is not an integer", getAttrPathStr(state)).debugThrow(); - return v.integer; + return v.integer(); } std::vector AttrCursor::getListOfStrings(EvalState & state) @@ -711,7 +711,7 @@ std::vector AttrCursor::getAttrs(EvalState & state) state.ctx.errors.make("'%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()); diff --git a/lix/libexpr/eval-inline.hh b/lix/libexpr/eval-inline.hh index 2281669db..a645c0aa9 100644 --- a/lix/libexpr/eval-inline.hh +++ b/lix/libexpr/eval-inline.hh @@ -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); } diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 22b575d6b..5a62c1402 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -25,6 +25,7 @@ #include "lix/libutil/exit.hh" #include "lix/libutil/json.hh" #include "symbol-table.hh" +#include "value.hh" #include #include @@ -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::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 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(size); + v._bigList.elems = gcAllocType(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( @@ -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 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 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(fun.lambda.fun->pattern.get()); + auto pattern = dynamic_cast(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("integer overflow in adding %1% + %2%", n, vTmp.integer).atPos(i_pos).debugThrow(); + state.ctx.errors + .make("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("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("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( "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( "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 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( "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: diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index ea5037727..f86b41997 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -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{attr.value->boolean}); + attrs.emplace(state.ctx.symbols[attr.name], Explicit{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 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::optional> expectType(state, nAttrs, *value, pos); std::optional 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::optional> 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(outputs->value->lambda.fun->pattern.get()); pattern) { + if (auto pattern = dynamic_cast(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("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 { attr.value->boolean }); + attrs.emplace(state.ctx.symbols[attr.name], Explicit{attr.value->boolean()}); } else if (t == nString) { attrs.emplace(state.ctx.symbols[attr.name], std::string(attr.value->str())); diff --git a/lix/libexpr/get-drvs.cc b/lix/libexpr/get-drvs.cc index 79fc3745f..7cdb0d2f8 100644 --- a/lix/libexpr/get-drvs.cc +++ b/lix/libexpr/get-drvs.cc @@ -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; } diff --git a/lix/libexpr/nixexpr.cc b/lix/libexpr/nixexpr.cc index 6ef91b8b3..8e96e8803 100644 --- a/lix/libexpr/nixexpr.cc +++ b/lix/libexpr/nixexpr.cc @@ -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"; diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 34c980bdb..88e90f0c7 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -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( - 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("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(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("'functionArgs' requires a function").debugThrow(); - AttrsPattern * formals = dynamic_cast(args[0]->lambda.fun->pattern.get()); + AttrsPattern * formals = dynamic_cast(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(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(); + auto ptr = args[0]->primOp()->fun.target(); 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; } diff --git a/lix/libexpr/primops/context.cc b/lix/libexpr/primops/context.cc index 12b26777f..7a6ddb3cb 100644 --- a/lix/libexpr/primops/context.cc +++ b/lix/libexpr/primops/context.cc @@ -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( @@ -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" diff --git a/lix/libexpr/primops/fetchClosure.cc b/lix/libexpr/primops/fetchClosure.cc index e8dd0aaf1..5ffd6e934 100644 --- a/lix/libexpr/primops/fetchClosure.cc +++ b/lix/libexpr/primops/fetchClosure.cc @@ -118,7 +118,7 @@ void prim_fetchClosure(EvalState & state, Value * * args, Value & v) std::optional toPath; std::optional 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"; diff --git a/lix/libexpr/primops/fetchMercurial.cc b/lix/libexpr/primops/fetchMercurial.cc index 47d4b1eb8..71c74a45c 100644 --- a/lix/libexpr/primops/fetchMercurial.cc +++ b/lix/libexpr/primops/fetchMercurial.cc @@ -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, diff --git a/lix/libexpr/primops/fetchTree.cc b/lix/libexpr/primops/fetchTree.cc index 69414b33e..9afd2fcf3 100644 --- a/lix/libexpr/primops/fetchTree.cc +++ b/lix/libexpr/primops/fetchTree.cc @@ -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( "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{attr.value->boolean}); + attrs.emplace(state.ctx.symbols[attr.name], Explicit{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("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"); diff --git a/lix/libexpr/print-ambiguous.cc b/lix/libexpr/print-ambiguous.cc index c2e6a637c..bc5180c96 100644 --- a/lix/libexpr/print-ambiguous.cc +++ b/lix/libexpr/print-ambiguous.cc @@ -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"); diff --git a/lix/libexpr/print.cc b/lix/libexpr/print.cc index 6b34405f1..e117f8641 100644 --- a/lix/libexpr/print.cc +++ b/lix/libexpr/print.cc @@ -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::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() diff --git a/lix/libexpr/value-to-json.cc b/lix/libexpr/value-to-json.cc index a12f44693..e78e729ef 100644 --- a/lix/libexpr/value-to-json.cc +++ b/lix/libexpr/value-to-json.cc @@ -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: diff --git a/lix/libexpr/value-to-xml.cc b/lix/libexpr/value-to-xml.cc index 421998b56..10571e962 100644 --- a/lix/libexpr/value-to-xml.cc +++ b/lix/libexpr/value-to-xml.cc @@ -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(v.lambda.fun->pattern.get()); formals) { + if (auto formals = dynamic_cast(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: diff --git a/lix/libexpr/value.cc b/lix/libexpr/value.cc index 4903db5d0..7e0902957 100644 --- a/lix/libexpr/value.cc +++ b/lix/libexpr/value.cc @@ -15,16 +15,16 @@ static void copyContextToValue(Value & v, const NixStringContext & context) { if (!context.empty()) { size_t n = 0; - v.string.context = gcAllocType(context.size() + 1); + v._string.context = gcAllocType(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() - && static_cast(thunk.expr)->dynamicAttrs.empty()) - || thunk.expr->try_cast() - || thunk.expr->try_cast()); + || (thunk().expr->try_cast() + && static_cast(thunk().expr)->dynamicAttrs.empty()) + || thunk().expr->try_cast() + || thunk().expr->try_cast()); } 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) diff --git a/lix/libexpr/value.hh b/lix/libexpr/value.hh index 1ace1cb6e..430b237c9 100644 --- a/lix/libexpr/value.hh +++ b/lix/libexpr/value.hh @@ -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(context.size() + 1); + this->_string.context = gcAllocType(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(context.size() + 1); + this->_string.context = gcAllocType(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(items.size()); + this->_bigList.size = items.size(); + this->_bigList.elems = gcAllocType(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; } }; diff --git a/lix/nix/bundle.cc b/lix/nix/bundle.cc index b322b5842..0bad9866c 100644 --- a/lix/nix/bundle.cc +++ b/lix/nix/bundle.cc @@ -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, ""); diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 191cb696f..a8a857f31 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -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(); + auto body = v.lambda().fun->body->try_cast(); if (!body) throw Error("overlay is not a function with two arguments, but only takes one"); if (body->body->try_cast()) @@ -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); diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 07c9f623c..2294fc294 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -369,7 +369,7 @@ static void showHelp(AsyncIoRoot & aio, std::vector 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; diff --git a/lix/nix/prefetch.cc b/lix/nix/prefetch.cc index 6eb2505ff..071c77f90 100644 --- a/lix/nix/prefetch.cc +++ b/lix/nix/prefetch.cc @@ -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"); } diff --git a/subprojects/nix-eval-jobs/src/worker.cc b/subprojects/nix-eval-jobs/src/worker.cc index b1a857eda..ac8286d1e 100644 --- a/subprojects/nix-eval-jobs/src/worker.cc +++ b/subprojects/nix-eval-jobs/src/worker.cc @@ -78,13 +78,13 @@ static std::string attrPathJoin(nix::JSON input) { static std::optional readConstituents(const nix::Value *v, nix::box_ptr &state, nix::ref &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 constituents; std::vector 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("derivation must have a ‘constituents’ " @@ -197,13 +197,13 @@ void worker(nix::ref 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, diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh index 76bb1564c..81e310b19 100644 --- a/tests/unit/libexpr-support/tests/libexpr.hh +++ b/tests/unit/libexpr-support/tests/libexpr.hh @@ -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; diff --git a/tests/unit/libexpr/primops.cc b/tests/unit/libexpr/primops.cc index ee1205746..bdda6bc1f 100644 --- a/tests/unit/libexpr/primops.cc +++ b/tests/unit/libexpr/primops.cc @@ -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(v.lambda.fun->pattern.get())); + ASSERT_NE(v.lambda().fun, nullptr); + ASSERT_TRUE(dynamic_cast(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)); } diff --git a/tests/unit/libexpr/trivial.cc b/tests/unit/libexpr/trivial.cc index 99d515273..6f150478a 100644 --- a/tests/unit/libexpr/trivial.cc +++ b/tests/unit/libexpr/trivial.cc @@ -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)); } diff --git a/tests/unit/libexpr/value/print.cc b/tests/unit/libexpr/value/print.cc index 4d3ae6271..ef77f6a07 100644 --- a/tests/unit/libexpr/value/print.cc +++ b/tests/unit/libexpr/value/print.cc @@ -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 " ]",