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
This commit is contained in:
eldritch horrors 2024-03-08 09:51:40 +01:00
parent 03f852b2c6
commit 1cf0fa0633
3 changed files with 46 additions and 18 deletions

View file

@ -1240,9 +1240,9 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
Value * vAttr; Value * vAttr;
if (hasOverrides && !i.second.inherited()) { if (hasOverrides && !i.second.inherited()) {
vAttr = state.allocValue(); vAttr = state.allocValue();
mkThunk(*vAttr, env2, i.second.e); mkThunk(*vAttr, *i.second.chooseByKind(&env2, &env, &env2), i.second.e);
} else } 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; 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));
} }
@ -1274,9 +1274,14 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
} }
} }
else else {
for (auto & i : attrs) for (auto & i : attrs) {
v.attrs->push_back(Attr(i.first, i.second.e->maybeThunk(state, env), i.second.pos)); 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. */ /* Dynamic attrs apply *after* rec and __overrides. */
for (auto & i : dynamicAttrs) { 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 while the inherited attributes are evaluated in the original
environment. */ environment. */
Displacement displ = 0; Displacement displ = 0;
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs) {
env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited() ? env : env2); env2.values[displ++] = i.second.e->maybeThunk(
state,
*i.second.chooseByKind(&env2, &env, &env2));
}
auto dts = state.debugRepl auto dts = state.debugRepl
? makeDebugTraceStacker( ? makeDebugTraceStacker(

View file

@ -332,16 +332,19 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
es.exprEnvs.insert(std::make_pair(this, env)); es.exprEnvs.insert(std::make_pair(this, env));
if (recursive) { 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; Displacement displ = 0;
for (auto & i : attrs) for (auto & i : attrs)
newEnv->vars.emplace_back(i.first, i.second.displ = displ++); newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
return newEnv;
}();
// No need to sort newEnv since attrs is in sorted order. // No need to sort newEnv since attrs is in sorted order.
for (auto & i : attrs) 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) { for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(es, newEnv); i.nameExpr->bindVars(es, newEnv);
@ -350,7 +353,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
} }
else { else {
for (auto & i : attrs) 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) { for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(es, env); 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) void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env)
{ {
auto newEnv = [&] () -> std::shared_ptr<const StaticEnv> {
auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs->attrs.size()); auto newEnv = std::make_shared<StaticEnv>(nullptr, env.get(), attrs->attrs.size());
Displacement displ = 0; Displacement displ = 0;
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
newEnv->vars.emplace_back(i.first, i.second.displ = displ++); newEnv->vars.emplace_back(i.first, i.second.displ = displ++);
return newEnv;
}();
// No need to sort newEnv since attrs->attrs is in sorted order. // No need to sort newEnv since attrs->attrs is in sorted order.
for (auto & i : attrs->attrs) 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) if (es.debugRepl)
es.exprEnvs.insert(std::make_pair(this, newEnv)); es.exprEnvs.insert(std::make_pair(this, newEnv));

View file

@ -172,6 +172,20 @@ struct ExprAttrs : Expr
AttrDef() { }; AttrDef() { };
bool inherited() const { return kind == Kind::Inherited; } 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; typedef std::map<Symbol, AttrDef> AttrDefs;
AttrDefs attrs; AttrDefs attrs;