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

Transformation pass that removes (binary) constraints on the anonymous records. More...

#include <FoldAnonymousRecords.h>

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

Public Member Functions

FoldAnonymousRecordsclone () 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 containsValidRecordConstraint (const Clause &)
 Determine if the clause contains at least one binary constraint which can be expanded. More...
 
VecOwn< LiteralexpandRecordBinaryConstraint (const BinaryConstraint &)
 Expand constraint on records position-wise. More...
 
bool isValidRecordConstraint (const Literal *literal)
 Determine if binary constraint can be expanded. More...
 
bool transform (TranslationUnit &translationUnit) override
 
void transformClause (const Clause &clause, VecOwn< Clause > &newClauses)
 Process a single clause. More...
 

Detailed Description

Transformation pass that removes (binary) constraints on the anonymous records.

After resolving aliases this is equivalent to completely removing anonymous records.

e.g. [a, b, c] = [x, y, z] → a = x, b = y, c = z. [a, b, c] != [x, y, z] → a != x b != y c != z (expanded to three new clauses)

In a single pass, in case of equalities a transformation expands a single level of records in every clause. (e.g. [[a]] = [[1]] => [a] = [1]) In case of inequalities, it expands at most a single inequality in every clause

This transformation does not resolve aliases. E.g. A = [a, b], A = [c, d] Thus it should be called in conjunction with ResolveAnonymousRecordAliases.

Definition at line 54 of file FoldAnonymousRecords.h.

Member Function Documentation

◆ clone()

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

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

Definition at line 66 of file FoldAnonymousRecords.h.

◆ containsValidRecordConstraint()

bool souffle::ast::transform::FoldAnonymousRecords::containsValidRecordConstraint ( const Clause clause)
private

Determine if the clause contains at least one binary constraint which can be expanded.

Definition at line 70 of file FoldAnonymousRecords.cpp.

74  {
75  VecOwn<Literal> replacedContraint;
76 

Referenced by transform().

◆ expandRecordBinaryConstraint()

VecOwn< Literal > souffle::ast::transform::FoldAnonymousRecords::expandRecordBinaryConstraint ( const BinaryConstraint constraint)
private

Expand constraint on records position-wise.

eg. [1, 2, 3] = [a, b, c] => vector(1 = a, 2 = b, 3 = c) [x, y, z] != [a, b, c] => vector(x != a, x != b, z != c)

Procedure assumes that argument has a valid operation, that children are of type RecordInit and that the size of both sides is the same

Definition at line 78 of file FoldAnonymousRecords.cpp.

88  {
89  auto newConstraint = mk<BinaryConstraint>(constraint.getBaseOperator(),
90  souffle::clone(leftChildren[i]), souffle::clone(rightChildren[i]));
91  replacedContraint.push_back(std::move(newConstraint));
92  }
93 
94  // Handle edge case. Empty records.
95  if (leftChildren.size() == 0) {
96  if (isEqConstraint(constraint.getBaseOperator())) {
97  replacedContraint.emplace_back(new BooleanConstraint(true));
98  } else {
99  replacedContraint.emplace_back(new BooleanConstraint(false));
100  }
101  }
102 
103  return replacedContraint;
104 }
105 
106 void FoldAnonymousRecords::transformClause(const Clause& clause, VecOwn<Clause>& newClauses) {
107  // If we have an inequality constraint, we need to create new clauses
108  // At most one inequality constraint will be expanded in a single pass.

Referenced by transformClause().

◆ getName()

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

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

Definition at line 62 of file FoldAnonymousRecords.h.

◆ isValidRecordConstraint()

bool souffle::ast::transform::FoldAnonymousRecords::isValidRecordConstraint ( const Literal literal)
private

Determine if binary constraint can be expanded.

Definition at line 41 of file FoldAnonymousRecords.cpp.

51  {
52  return false;
53  }
54 
55  // Check if records are of the same size.
56  if (leftRecord->getChildNodes().size() != rightRecord->getChildNodes().size()) {
57  return false;
58  }
59 
60  // Check if operator is "=" or "!="
61  auto op = constraint->getBaseOperator();
62 
64 }
65 
66 bool FoldAnonymousRecords::containsValidRecordConstraint(const Clause& clause) {
67  bool contains = false;
68  visitDepthFirst(clause, [&](const BinaryConstraint& binary) {

Referenced by transformClause().

◆ transform()

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

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

Definition at line 164 of file FoldAnonymousRecords.cpp.

166  : program.getClauses()) {
167  if (containsValidRecordConstraint(*clause)) {
168  changed = true;
169  transformClause(*clause, newClauses);
170  } else {
171  newClauses.emplace_back(clause->clone());
172  }
173  }
174 
175  // Update Program.
176  if (changed) {
177  program.setClauses(std::move(newClauses));
178  }
179  return changed;
180 }
181 
182 } // namespace souffle::ast::transform

References containsValidRecordConstraint(), and transformClause().

Here is the call graph for this function:

◆ transformClause()

void souffle::ast::transform::FoldAnonymousRecords::transformClause ( const Clause clause,
VecOwn< Clause > &  newClauses 
)
private

Process a single clause.

@parem clause Clause to be processed.

Parameters
newClausesa destination for the newly produced clauses.

Definition at line 110 of file FoldAnonymousRecords.cpp.

112  : clause.getBodyLiterals()) {
113  if (isValidRecordConstraint(literal)) {
114  const BinaryConstraint& constraint = dynamic_cast<BinaryConstraint&>(*literal);
115 
116  // Simple case, [a_0, ..., a_n] = [b_0, ..., b_n]
117  if (isEqConstraint(constraint.getBaseOperator())) {
118  auto transformedLiterals = expandRecordBinaryConstraint(constraint);
119  std::move(std::begin(transformedLiterals), std::end(transformedLiterals),
120  std::back_inserter(newBody));
121 
122  // else if: Case [a_0, ..., a_n] != [b_0, ..., b_n].
123  // track single such case, it will be expanded in the end.
124  } else if (neqConstraint == nullptr) {
125  neqConstraint = dynamic_cast<BinaryConstraint*>(literal);
126 
127  // Else: repeated inequality.
128  } else {
129  newBody.push_back(souffle::clone(literal));
130  }
131 
132  // else, we simply copy the literal.
133  } else {
134  newBody.push_back(souffle::clone(literal));
135  }
136  }
137 
138  // If no inequality: create a single modified clause.
139  if (neqConstraint == nullptr) {
140  auto newClause = souffle::clone(&clause);
141  newClause->setBodyLiterals(std::move(newBody));
142  newClauses.emplace_back(std::move(newClause));
143 
144  // Else: For each pair in negation, we need an extra clause.
145  } else {
146  auto transformedLiterals = expandRecordBinaryConstraint(*neqConstraint);
147 
148  for (auto it = begin(transformedLiterals); it != end(transformedLiterals); ++it) {
149  auto newClause = souffle::clone(&clause);
150  auto copyBody = souffle::clone(newBody);
151  copyBody.push_back(std::move(*it));
152 
153  newClause->setBodyLiterals(std::move(copyBody));
154 
155  newClauses.push_back(std::move(newClause));
156  }
157  }
158 }
159 
160 bool FoldAnonymousRecords::transform(TranslationUnit& translationUnit) {
161  bool changed = false;
162  Program& program = translationUnit.getProgram();

References souffle::clone(), expandRecordBinaryConstraint(), souffle::ast::BinaryConstraint::getBaseOperator(), souffle::isEqConstraint(), and isValidRecordConstraint().

Referenced by transform().

Here is the call graph for this function:

The documentation for this class was generated from the following files:
souffle::contains
bool contains(const C &container, const typename C::value_type &element)
A utility to check generically whether a given element is contained in a given container.
Definition: ContainerUtil.h:75
souffle::ast::transform::FoldAnonymousRecords::isValidRecordConstraint
bool isValidRecordConstraint(const Literal *literal)
Determine if binary constraint can be expanded.
Definition: FoldAnonymousRecords.cpp:41
souffle::ast::transform::FoldAnonymousRecords::containsValidRecordConstraint
bool containsValidRecordConstraint(const Clause &)
Determine if the clause contains at least one binary constraint which can be expanded.
Definition: FoldAnonymousRecords.cpp:70
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
i
size_t i
Definition: json11.h:663
souffle::negatedConstraintOp
BinaryConstraintOp negatedConstraintOp(const BinaryConstraintOp op)
Negated Constraint Operator Each operator requires a negated operator which is necessary for the expa...
Definition: BinaryConstraintOps.h:297
souffle::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
souffle::ast::transform::FoldAnonymousRecords::transform
bool transform(TranslationUnit &translationUnit) override
Definition: FoldAnonymousRecords.cpp:164
souffle::ast::transform::FoldAnonymousRecords::transformClause
void transformClause(const Clause &clause, VecOwn< Clause > &newClauses)
Process a single clause.
Definition: FoldAnonymousRecords.cpp:110
souffle::ast::transform::FoldAnonymousRecords::expandRecordBinaryConstraint
VecOwn< Literal > expandRecordBinaryConstraint(const BinaryConstraint &)
Expand constraint on records position-wise.
Definition: FoldAnonymousRecords.cpp:78
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