aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-08 09:51:40 +0100
committereldritch horrors <pennae@lix.systems>2024-03-10 03:18:32 -0600
commit1cf0fa06332712e41e132dd8fce1198c89351e6e (patch)
tree6bd76f019950a5f40c5420611bfe66a5df252da7 /src
parent03f852b2c69233667de839a4777331114304c983 (diff)
add ExprAttrs::AttrDef::chooseByKind
in place of inherited() — not quite useful yet since we don't distinguish plain and inheritFrom attr kinds so far. (cherry picked from commit 1f542adb3e18e7078e6a589182a53a47d971748a) Change-Id: If948c9d43e875de18f213a73a06a36f7c335b536
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/eval.cc22
-rw-r--r--src/libexpr/nixexpr.cc28
-rw-r--r--src/libexpr/nixexpr.hh14
3 files changed, 46 insertions, 18 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index bf4c917c6..e30c32d92 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1240,9 +1240,9 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
Value * vAttr;
if (hasOverrides && !i.second.inherited()) {
vAttr = state.allocValue();
- mkThunk(*vAttr, env2, i.second.e);
+ mkThunk(*vAttr, *i.second.chooseByKind(&env2, &env, &env2), i.second.e);
} else
- vAttr = i.second.e->maybeThunk(state, i.second.inherited() ? env : env2);
+ vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, &env2));
env2.values[displ++] = vAttr;
v.attrs->push_back(Attr(i.first, vAttr, i.second.pos));
}
@@ -1274,9 +1274,14 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
}
}
- else
- for (auto & i : attrs)
- v.attrs->push_back(Attr(i.first, i.second.e->maybeThunk(state, env), i.second.pos));
+ else {
+ for (auto & i : attrs) {
+ v.attrs->push_back(Attr(
+ i.first,
+ i.second.e->maybeThunk(state, *i.second.chooseByKind(&env, &env, &env)),
+ i.second.pos));
+ }
+ }
/* Dynamic attrs apply *after* rec and __overrides. */
for (auto & i : dynamicAttrs) {
@@ -1312,8 +1317,11 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
while the inherited attributes are evaluated in the original
environment. */
Displacement displ = 0;
- for (auto & i : attrs->attrs)
- env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited() ? env : env2);
+ for (auto & i : attrs->attrs) {
+ env2.values[displ++] = i.second.e->maybeThunk(
+ state,
+ *i.second.chooseByKind(&env2, &env, &env2));
+ }
auto dts = state.debugRepl
? makeDebugTraceStacker(
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index a12fd62c0..531d5027c 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -332,16 +332,19 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
es.exprEnvs.insert(std::make_pair(this, env));
if (recursive) {
- auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), recursive ? attrs.size() : 0);
+ auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
+ auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs.size());
- Displacement displ = 0;
- for (auto & i : attrs)
- newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
+ Displacement displ = 0;
+ for (auto & i : attrs)
+ newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
+ return newEnv;
+ }();
// No need to sort newEnv since attrs is in sorted order.
for (auto & i : attrs)
- i.second.e->bindVars(es, i.second.inherited() ? env : newEnv);
+ i.second.e->bindVars(es, i.second.chooseByKind(newEnv, env, newEnv));
for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(es, newEnv);
@@ -350,7 +353,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
}
else {
for (auto & i : attrs)
- i.second.e->bindVars(es, env);
+ i.second.e->bindVars(es, i.second.chooseByKind(env, env, env));
for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(es, env);
@@ -407,16 +410,19 @@ void ExprCall::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{
- auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs->attrs.size());
+ auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
+ auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs->attrs.size());
- Displacement displ = 0;
- for (auto & i : attrs->attrs)
- newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
+ Displacement displ = 0;
+ for (auto & i : attrs->attrs)
+ newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
+ return newEnv;
+ }();
// No need to sort newEnv since attrs->attrs is in sorted order.
for (auto & i : attrs->attrs)
- i.second.e->bindVars(es, i.second.inherited() ? env : newEnv);
+ i.second.e->bindVars(es, i.second.chooseByKind(newEnv, env, newEnv));
if (es.debugRepl)
es.exprEnvs.insert(std::make_pair(this, newEnv));
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index fe75592f0..246221c0f 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -172,6 +172,20 @@ struct ExprAttrs : Expr
AttrDef() { };
bool inherited() const { return kind == Kind::Inherited; }
+
+ template<typename T>
+ const T & chooseByKind(const T & plain, const T & inherited, const T & inheritedFrom) const
+ {
+ switch (kind) {
+ case Kind::Plain:
+ return plain;
+ case Kind::Inherited:
+ return inherited;
+ default:
+ case Kind::InheritedFrom:
+ return inheritedFrom;
+ }
+ }
};
typedef std::map<Symbol, AttrDef> AttrDefs;
AttrDefs attrs;