preserve information about whether/how an attribute was inherited

(cherry picked from commit c66ee57edc6cac3571bfbf77d0c0ea4d25b4e805)
Change-Id: Ie8606a8b2f5946c87dd4d16b7b46203e199a4cc1
This commit is contained in:
eldritch horrors 2024-03-08 09:51:27 +01:00
parent 3e43f4aeff
commit 03f852b2c6
5 changed files with 31 additions and 13 deletions

View file

@ -1238,11 +1238,11 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
Displacement displ = 0; Displacement displ = 0;
for (auto & i : attrs) { for (auto & i : attrs) {
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, 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.inherited() ? 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));
} }
@ -1313,7 +1313,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
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.inherited() ? env : env2);
auto dts = state.debugRepl auto dts = state.debugRepl
? makeDebugTraceStacker( ? makeDebugTraceStacker(

View file

@ -80,7 +80,7 @@ void ExprAttrs::show(const SymbolTable & symbols, std::ostream & str) const
return sa < sb; return sa < sb;
}); });
for (auto & i : sorted) { for (auto & i : sorted) {
if (i->second.inherited) if (i->second.inherited())
str << "inherit " << symbols[i->first] << " " << "; "; str << "inherit " << symbols[i->first] << " " << "; ";
else { else {
str << symbols[i->first] << " = "; str << symbols[i->first] << " = ";
@ -151,7 +151,7 @@ void ExprLet::show(const SymbolTable & symbols, std::ostream & str) const
{ {
str << "(let "; str << "(let ";
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
if (i.second.inherited) { if (i.second.inherited()) {
str << "inherit " << symbols[i.first] << "; "; str << "inherit " << symbols[i.first] << "; ";
} }
else { else {
@ -341,7 +341,7 @@ void ExprAttrs::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv>
// 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.inherited() ? env : newEnv);
for (auto & i : dynamicAttrs) { for (auto & i : dynamicAttrs) {
i.nameExpr->bindVars(es, newEnv); i.nameExpr->bindVars(es, newEnv);
@ -416,7 +416,7 @@ void ExprLet::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
// 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.inherited() ? 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

@ -154,13 +154,24 @@ struct ExprAttrs : Expr
bool recursive; bool recursive;
PosIdx pos; PosIdx pos;
struct AttrDef { struct AttrDef {
bool inherited; enum class Kind {
/** `attr = expr;` */
Plain,
/** `inherit attr1 attrn;` */
Inherited,
/** `inherit (expr) attr1 attrn;` */
InheritedFrom,
};
Kind kind;
Expr * e; Expr * e;
PosIdx pos; PosIdx pos;
Displacement displ; // displacement Displacement displ; // displacement
AttrDef(Expr * e, const PosIdx & pos, bool inherited=false) AttrDef(Expr * e, const PosIdx & pos, Kind kind = Kind::Plain)
: inherited(inherited), e(e), pos(pos) { }; : kind(kind), e(e), pos(pos) { };
AttrDef() { }; AttrDef() { };
bool inherited() const { return kind == Kind::Inherited; }
}; };
typedef std::map<Symbol, AttrDef> AttrDefs; typedef std::map<Symbol, AttrDef> AttrDefs;
AttrDefs attrs; AttrDefs attrs;

View file

@ -88,7 +88,7 @@ inline void ParserState::addAttr(ExprAttrs * attrs, AttrPath && attrPath, Expr *
if (i->symbol) { if (i->symbol) {
ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol); ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(i->symbol);
if (j != attrs->attrs.end()) { if (j != attrs->attrs.end()) {
if (!j->second.inherited) { if (!j->second.inherited()) {
ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e); ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
if (!attrs2) dupAttr(attrPath, pos, j->second.pos); if (!attrs2) dupAttr(attrPath, pos, j->second.pos);
attrs = attrs2; attrs = attrs2;

View file

@ -311,7 +311,9 @@ binds
if ($$->attrs.find(i.symbol) != $$->attrs.end()) if ($$->attrs.find(i.symbol) != $$->attrs.end())
state->dupAttr(i.symbol, state->at(@3), $$->attrs[i.symbol].pos); state->dupAttr(i.symbol, state->at(@3), $$->attrs[i.symbol].pos);
auto pos = state->at(@3); auto pos = state->at(@3);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, true)); $$->attrs.emplace(
i.symbol,
ExprAttrs::AttrDef(new ExprVar(CUR_POS, i.symbol), pos, ExprAttrs::AttrDef::Kind::Inherited));
} }
delete $3; delete $3;
} }
@ -321,7 +323,12 @@ binds
for (auto & i : *$6) { for (auto & i : *$6) {
if ($$->attrs.find(i.symbol) != $$->attrs.end()) if ($$->attrs.find(i.symbol) != $$->attrs.end())
state->dupAttr(i.symbol, state->at(@6), $$->attrs[i.symbol].pos); state->dupAttr(i.symbol, state->at(@6), $$->attrs[i.symbol].pos);
$$->attrs.emplace(i.symbol, ExprAttrs::AttrDef(new ExprSelect(CUR_POS, $4, i.symbol), state->at(@6))); $$->attrs.emplace(
i.symbol,
ExprAttrs::AttrDef(
new ExprSelect(CUR_POS, $4, i.symbol),
state->at(@6),
ExprAttrs::AttrDef::Kind::InheritedFrom));
} }
delete $6; delete $6;
} }