souffle  2.0.2-371-g6315b36
Public Member Functions | Private Member Functions
souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer Class Reference

Transformation pass to rename aggregation variables to make them unique. More...

#include <SimplifyAggregateTargetExpression.h>

Inheritance diagram for souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer:
Inheritance graph
Collaboration diagram for souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer:
Collaboration graph

Public Member Functions

SimplifyAggregateTargetExpressionTransformerclone () const override
 
std::string getName () const override
 
- Public Member Functions inherited from souffle::ast::transform::Transformer
bool apply (TranslationUnit &translationUnit)
 
virtual ~Transformer ()=default
 

Private Member Functions

bool transform (TranslationUnit &translationUnit) override
 

Detailed Description

Transformation pass to rename aggregation variables to make them unique.

Definition at line 29 of file SimplifyAggregateTargetExpression.h.

Member Function Documentation

◆ clone()

SimplifyAggregateTargetExpressionTransformer* souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer::clone ( ) const
inlineoverridevirtual

◆ getName()

std::string souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer::getName ( ) const
inlineoverridevirtual

Implements souffle::ast::transform::Transformer.

Definition at line 35 of file SimplifyAggregateTargetExpression.h.

35  :
36  bool transform(TranslationUnit& translationUnit) override;
37 };

◆ transform()

bool souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer::transform ( TranslationUnit translationUnit)
overrideprivatevirtual

Implements souffle::ast::transform::Transformer.

Definition at line 29 of file SimplifyAggregateTargetExpression.cpp.

35  : public NodeMapper {
36  mutable bool changed = false;
37  TranslationUnit* tu;
38  const Clause* originatingClause;
39 
40  AggregateTESimplifier(TranslationUnit* unit, const Clause* c) : tu(unit), originatingClause(c) {}
41 
42  bool causedChange() {
43  return changed;
44  }
45  std::unique_ptr<Node> operator()(std::unique_ptr<Node> node) const override {
46  if (auto* aggregate = dynamic_cast<Aggregator*>(node.get())) {
47  // Check if the target expression is complex
48  if (aggregate->getTargetExpression() != nullptr &&
49  dynamic_cast<const Variable*>(aggregate->getTargetExpression()) == nullptr) {
50  // If it's complex, come up with a unique variable name to stand
51  // in the place of the target expression. This will be set equal to the target
52  // expression.
53  // What we might have though now is that a variable in the TE was shadowing
54  // a variable from the outer scope. Now we have "forgotten" this shadowing
55  // and need to restore it by scoping that variable properly.
56  // We know that a variable from the TE is shadowing another variable
57  // if a variable with the same name appears range-restricted in the outer scope.
58 
59  // make a unique target expression variable
60  auto newTargetExpression =
61  mk<Variable>(analysis::findUniqueVariableName(*originatingClause, "x"));
62  auto equalityLiteral = std::make_unique<BinaryConstraint>(BinaryConstraintOp::EQ,
63  souffle::clone(newTargetExpression),
64  souffle::clone(aggregate->getTargetExpression()));
65  std::vector<std::unique_ptr<Literal>> newBody;
66  for (Literal* literal : aggregate->getBodyLiterals()) {
67  newBody.push_back(souffle::clone(literal));
68  }
69  newBody.push_back(std::move(equalityLiteral));
70  // If there are occurrences of the same variable in the outer scope
71  // Then we need to be careful. There are two ensuing situations:
72  // 1) The variable in the outer scope is ungrounded (or occurs in the head)
73  // => We have a witness, and we shouldn't rename this variable, because it is not
74  // local.
75  // 2) The variable in the outer scope is grounded
76  // => We need to rename this because it is a local variable (the grounding of the
77  // outer scope
78  // variable is shadowed by occurrence of the variable in the target expression)
79 
80  // We already have a way to find witnesses and also to find variables occurring outside
81  // this aggregate. We will take the set minus of variablesOccurringOutside - witnesses.
82  // Whichever variables are in this set need to be renamed within the aggregate subclause.
83  auto witnesses = analysis::getWitnessVariables(*tu, *originatingClause, *aggregate);
84  std::set<std::string> varsOutside =
85  analysis::getVariablesOutsideAggregate(*originatingClause, *aggregate);
86 
87  std::set<std::string> varsGroundedOutside;
88  for (auto& varName : varsOutside) {
89  if (witnesses.find(varName) == witnesses.end()) {
90  varsGroundedOutside.insert(varName);
91  }
92  }
93  // rename all variables that were grounded outside
94  // (we had an occurrence of the same variable name in the TE,
95  // the implication being that the occurrence of that variable
96  // in the scope of the aggregate subclause should be local,
97  // not grounded from the outer scope (injected)
98  visitDepthFirst(*aggregate->getTargetExpression(), [&](const Variable& v) {
99  if (varsGroundedOutside.find(v.getName()) != varsGroundedOutside.end()) {
100  // rename it everywhere in the body so that we've scoped this properly.
101  std::string newVarName =
102  analysis::findUniqueVariableName(*originatingClause, v.getName());
103  for (auto& literal : newBody) {
104  visitDepthFirst(*literal, [&](const Variable& literalVar) {
105  if (literalVar == v) {
106  const_cast<Variable&>(literalVar).setName(newVarName);
107  }
108  });
109  }
110  }
111  });
112 
113  // set up a new aggregate to replace this one
114  auto newAggregate = mk<Aggregator>(
115  aggregate->getBaseOperator(), std::move(newTargetExpression), std::move(newBody));
116  changed = true;
117  return newAggregate;
118  }
119  }
120  node->apply(*this);
121  return node;
122  }
123  };
124 
125  bool changed = false;
126  visitDepthFirst(program, [&](const Clause& clause) {
127  Own<Clause> oldClause = souffle::clone(&clause);
128  AggregateTESimplifier teSimplifier(&translationUnit, oldClause.get());
129  const_cast<Clause&>(clause).apply(teSimplifier);
130  changed = changed || teSimplifier.causedChange();
131  });
132  return changed;
133 }
134 } // namespace souffle::ast::transform

References souffle::clone(), souffle::EQ, souffle::ast::analysis::findUniqueVariableName(), souffle::ast::analysis::getVariablesOutsideAggregate(), souffle::ast::analysis::getWitnessVariables(), and souffle::ast::visitDepthFirst().

Here is the call graph for this function:

The documentation for this class was generated from the following files:
souffle::BinaryConstraintOp::EQ
@ EQ
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
souffle::ast::analysis::getVariablesOutsideAggregate
std::set< std::string > getVariablesOutsideAggregate(const Clause &clause, const Aggregator &aggregate)
Computes the set of variables occurring outside the aggregate.
Definition: Aggregate.cpp:164
souffle::ast::analysis::findUniqueVariableName
std::string findUniqueVariableName(const Clause &clause, std::string base)
Find a variable name using base to form a string like base1 Use this when you need to limit the scope...
Definition: Aggregate.cpp:179
souffle::ast::transform::SimplifyAggregateTargetExpressionTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: SimplifyAggregateTargetExpression.cpp:29
souffle::ast::visitDepthFirst
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Definition: Visitor.h:273
souffle::ast::transform::Transformer::apply
bool apply(TranslationUnit &translationUnit)
Definition: Transformer.cpp:29
souffle::ast::analysis::getWitnessVariables
std::set< std::string > getWitnessVariables(const TranslationUnit &tu, const Clause &clause, const Aggregator &aggregate)
Computes the set of witness variables that are used in the aggregate A variable is a witness if it oc...
Definition: Aggregate.cpp:75