aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/nixexpr.cc
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-08 09:52:03 +0100
committereldritch horrors <pennae@lix.systems>2024-03-10 03:18:32 -0600
commit2a84123631c2a86df54326f9025660b4684f95bf (patch)
treedb643200780ae63ae5bb234955708ac8c2d04b3c /src/libexpr/nixexpr.cc
parentbf19eebb9b905c1366fa96ae9b1b9f06aa1fe672 (diff)
group inherit by source during Expr::show
for plain inherits this is really just a stylistic choice, but for inherit-from it actually fixes an exponential size increase problem during expr printing (as may happen during assertion failure reporting, on during duplicate attr detection in the parser) (cherry picked from commit ecf8b12d60ad2929f9998666cf0966475b91e291) Change-Id: Ie55f0cb01a37e766414c31f8d40f51c2c7d106b0
Diffstat (limited to 'src/libexpr/nixexpr.cc')
-rw-r--r--src/libexpr/nixexpr.cc32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 525b2440b..c9d42cea5 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -77,10 +77,36 @@ void ExprAttrs::showBindings(const SymbolTable & symbols, std::ostream & str) co
std::string_view sa = symbols[a->first], sb = symbols[b->first];
return sa < sb;
});
+ std::vector<Symbol> inherits;
+ std::map<Expr *, std::vector<Symbol>> inheritsFrom;
for (auto & i : sorted) {
- if (i->second.inherited())
- str << "inherit " << symbols[i->first] << " " << "; ";
- else {
+ switch (i->second.kind) {
+ case AttrDef::Kind::Plain:
+ break;
+ case AttrDef::Kind::Inherited:
+ inherits.push_back(i->first);
+ break;
+ case AttrDef::Kind::InheritedFrom: {
+ auto & select = dynamic_cast<ExprSelect &>(*i->second.e);
+ inheritsFrom[select.e].push_back(i->first);
+ break;
+ }
+ }
+ }
+ if (!inherits.empty()) {
+ str << "inherit";
+ for (auto sym : inherits) str << " " << symbols[sym];
+ str << "; ";
+ }
+ for (const auto & [from, syms] : inheritsFrom) {
+ str << "inherit (";
+ from->show(symbols, str);
+ str << ")";
+ for (auto sym : syms) str << " " << symbols[sym];
+ str << "; ";
+ }
+ for (auto & i : sorted) {
+ if (i->second.kind == AttrDef::Kind::Plain) {
str << symbols[i->first] << " = ";
i->second.e->show(symbols, str);
str << "; ";