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

Transformation pass to eliminate grounded aliases. More...

#include <ResolveAliases.h>

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

Public Member Functions

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

Static Public Member Functions

static Own< ClauseremoveComplexTermsInAtoms (const Clause &clause)
 Removes complex terms in atoms, replacing them with constrained variables. More...
 
static Own< ClauseremoveTrivialEquality (const Clause &clause)
 Removes trivial equalities of the form t = t from the given clause. More...
 
static Own< ClauseresolveAliases (const Clause &clause)
 Converts the given clause into a version without variables aliasing grounded variables. More...
 

Private Member Functions

bool transform (TranslationUnit &translationUnit) override
 

Detailed Description

Transformation pass to eliminate grounded aliases.

e.g. resolve: a(r) , r = [x,y] => a(x,y) e.g. resolve: a(x) , !b(y) , y = x => a(x) , !b(x)

Definition at line 35 of file ResolveAliases.h.

Member Function Documentation

◆ clone()

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

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

Definition at line 70 of file ResolveAliases.h.

◆ getName()

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

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

Definition at line 41 of file ResolveAliases.h.

62  {

◆ removeComplexTermsInAtoms()

Own< Clause > souffle::ast::transform::ResolveAliasesTransformer::removeComplexTermsInAtoms ( const Clause clause)
static

Removes complex terms in atoms, replacing them with constrained variables.

Parameters
clausethe clause to be processed
Returns
a modified clone of the processed clause

Definition at line 389 of file ResolveAliases.cpp.

390  : atoms) {
391  for (const Argument* arg : atom->getArguments()) {
392  // ignore if not a functor
393  if (!isA<Functor>(arg)) {
394  continue;
395  }
396 
397  // add this functor if not seen yet
398  if (!any_of(terms, [&](const Argument* cur) { return *cur == *arg; })) {
399  terms.push_back(arg);
400  }
401  }
402  }
403 
404  // find all functors in records too
405  visitDepthFirst(atoms, [&](const RecordInit& rec) {
406  for (const Argument* arg : rec.getArguments()) {
407  // ignore if not a functor
408  if (!isA<Functor>(arg)) {
409  continue;
410  }
411 
412  // add this functor if not seen yet
413  if (!any_of(terms, [&](const Argument* cur) { return *cur == *arg; })) {
414  terms.push_back(arg);
415  }
416  }
417  });
418 
419  // substitute them with new variables (a real map would compare pointers)
420  using substitution_map = std::vector<std::pair<Own<Argument>, Own<ast::Variable>>>;
421  substitution_map termToVar;
422 
423  static int varCounter = 0;
424  for (const Argument* arg : terms) {
425  // create a new mapping for this term
426  auto term = souffle::clone(arg);
427  auto newVariable = mk<ast::Variable>(" _tmp_" + toString(varCounter++));
428  termToVar.push_back(std::make_pair(std::move(term), std::move(newVariable)));
429  }
430 
431  // apply mapping to replace the terms with the variables
432  struct Update : public NodeMapper {
433  const substitution_map& map;
434 
435  Update(const substitution_map& map) : map(map) {}
436 
437  Own<Node> operator()(Own<Node> node) const override {
438  // check whether node needs to be replaced
439  for (const auto& pair : map) {
440  auto& term = pair.first;
441  auto& variable = pair.second;
442 
443  if (*term == *node) {
444  return souffle::clone(variable);
445  }
446  }
447 
448  // continue recursively
449  node->apply(*this);
450  return node;
451  }
452  };
453 
454  // update atoms
455  Update update(termToVar);
456  for (Atom* atom : atoms) {
457  atom->apply(update);
458  }
459 
460  // add the necessary variable constraints to the clause
461  for (const auto& pair : termToVar) {
462  auto& term = pair.first;
463  auto& variable = pair.second;
464 
465  res->addToBody(
466  mk<BinaryConstraint>(BinaryConstraintOp::EQ, souffle::clone(variable), souffle::clone(term)));
467  }
468 
469  return res;
470 }
471 
472 bool ResolveAliasesTransformer::transform(TranslationUnit& translationUnit) {
473  bool changed = false;
474  Program& program = translationUnit.getProgram();
475 
476  // get all clauses
477  std::vector<const Clause*> clauses;

References souffle::any_of().

Here is the call graph for this function:

◆ removeTrivialEquality()

Own< Clause > souffle::ast::transform::ResolveAliasesTransformer::removeTrivialEquality ( const Clause clause)
static

Removes trivial equalities of the form t = t from the given clause.

Parameters
clausethe clause to be processed
Returns
a modified clone of the given clause

Definition at line 368 of file ResolveAliases.cpp.

368  {
369  if (*constraint->getLHS() == *constraint->getRHS()) {
370  continue; // skip this one
371  }
372  }
373  }
374 
375  res->addToBody(souffle::clone(literal));
376  }
377 
378  // done
379  return res;
380 }
381 
382 Own<Clause> ResolveAliasesTransformer::removeComplexTermsInAtoms(const Clause& clause) {
383  Own<Clause> res(clause.clone());
384 
385  // get list of atoms
386  std::vector<Atom*> atoms = getBodyLiterals<Atom>(*res);
387 

◆ resolveAliases()

Own< Clause > souffle::ast::transform::ResolveAliasesTransformer::resolveAliases ( const Clause clause)
static

Converts the given clause into a version without variables aliasing grounded variables.

Parameters
clausethe clause to be processed
Returns
a modified clone of the processed clause

Definition at line 214 of file ResolveAliases.cpp.

214  { return isA<RecordInit>(&arg); };
215 
216  // tests whether something is a multi-result functor
217  auto isMultiResultFunctor = [&](const Argument& arg) {
218  const auto* inf = dynamic_cast<const IntrinsicFunctor*>(&arg);
219  if (inf == nullptr) return false;
221  };
222 
223  // tests whether a value `a` occurs in a term `b`
224  auto occurs = [](const Argument& a, const Argument& b) {
225  bool res = false;
226  visitDepthFirst(b, [&](const Argument& arg) { res = (res || (arg == a)); });
227  return res;
228  };
229 
230  // variables appearing as functorless arguments in atoms or records should not
231  // be resolved
232  std::set<std::string> baseGroundedVariables;
233  for (const auto* atom : getBodyLiterals<Atom>(clause)) {
234  for (const Argument* arg : atom->getArguments()) {
235  if (const auto* var = dynamic_cast<const ast::Variable*>(arg)) {
236  baseGroundedVariables.insert(var->getName());
237  }
238  }
239  visitDepthFirst(*atom, [&](const RecordInit& rec) {
240  for (const Argument* arg : rec.getArguments()) {
241  if (const auto* var = dynamic_cast<const ast::Variable*>(arg)) {
242  baseGroundedVariables.insert(var->getName());
243  }
244  }
245  });
246  }
247 
248  // I) extract equations
249  std::vector<Equation> equations;
250  visitDepthFirst(clause, [&](const BinaryConstraint& constraint) {
251  if (isEqConstraint(constraint.getBaseOperator())) {
252  equations.push_back(Equation(constraint.getLHS(), constraint.getRHS()));
253  }
254  });
255 
256  // II) compute unifying substitution
257  Substitution substitution;
258 
259  // a utility for processing newly identified mappings
260  auto newMapping = [&](const std::string& var, const Argument* term) {
261  // found a new substitution
262  Substitution newMapping(var, term);
263 
264  // apply substitution to all remaining equations
265  for (auto& equation : equations) {
266  equation.apply(newMapping);
267  }
268 
269  // add mapping v -> t to substitution
270  substitution.append(newMapping);
271  };
272 
273  while (!equations.empty()) {
274  // get next equation to compute
275  Equation equation = equations.back();
276  equations.pop_back();
277 
278  // shortcuts for left/right
279  const Argument& lhs = *equation.lhs;
280  const Argument& rhs = *equation.rhs;
281 
282  // #1: t = t => skip
283  if (lhs == rhs) {
284  continue;
285  }
286 
287  // #2: [..] = [..] => decompose
288  if (isRec(lhs) && isRec(rhs)) {
289  // get arguments
290  const auto& lhs_args = static_cast<const RecordInit&>(lhs).getArguments();
291  const auto& rhs_args = static_cast<const RecordInit&>(rhs).getArguments();
292 
293  // make sure sizes are identical
294  assert(lhs_args.size() == rhs_args.size() && "Record lengths not equal");
295 
296  // create new equalities
297  for (size_t i = 0; i < lhs_args.size(); i++) {
298  equations.push_back(Equation(lhs_args[i], rhs_args[i]));
299  }
300 
301  continue;
302  }
303 
304  // #3: neither is a variable => skip
305  if (!isVar(lhs) && !isVar(rhs)) {
306  continue;
307  }
308 
309  // #4: v = w => add mapping
310  if (isVar(lhs) && isVar(rhs)) {
311  auto& var = static_cast<const ast::Variable&>(lhs);
312  newMapping(var.getName(), &rhs);
313  continue;
314  }
315 
316  // #5: t = v => swap
317  if (!isVar(lhs)) {
318  equations.push_back(Equation(rhs, lhs));
319  continue;
320  }
321 
322  // now we know lhs is a variable
323  assert(isVar(lhs));
324 
325  // therefore, we have v = t
326  const auto& v = static_cast<const ast::Variable&>(lhs);
327  const Argument& t = rhs;
328 
329  // #6: t is a multi-result functor => skip
330  if (isMultiResultFunctor(t)) {
331  continue;
332  }
333 
334  // #7: v occurs in t => skip
335  if (occurs(v, t)) {
336  continue;
337  }
338 
339  assert(!occurs(v, t));
340 
341  // #8: t is a record => add mapping
342  if (isRec(t)) {
343  newMapping(v.getName(), &t);
344  continue;
345  }
346 
347  // #9: v is already grounded => skip
348  auto pos = baseGroundedVariables.find(v.getName());
349  if (pos != baseGroundedVariables.end()) {
350  continue;
351  }
352 
353  // add new mapping
354  newMapping(v.getName(), &t);
355  }
356 
357  // III) compute resulting clause
358  return substitution(souffle::clone(&clause));
359 }
360 
361 Own<Clause> ResolveAliasesTransformer::removeTrivialEquality(const Clause& clause) {
362  Own<Clause> res(cloneHead(&clause));
363 
364  // add all literals, except filtering out t = t constraints
365  for (Literal* literal : clause.getBodyLiterals()) {
366  if (auto* constraint = dynamic_cast<BinaryConstraint*>(literal)) {

◆ transform()

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

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

Definition at line 479 of file ResolveAliases.cpp.

479  : getClauses(program, rel)) {
480  clauses.push_back(clause);
481  }
482  });
483 
484  // clean all clauses
485  for (const Clause* clause : clauses) {
486  // -- Step 1 --
487  // get rid of aliases
488  Own<Clause> noAlias = resolveAliases(*clause);
489 
490  // clean up equalities
491  Own<Clause> cleaned = removeTrivialEquality(*noAlias);
492 
493  // -- Step 2 --
494  // restore simple terms in atoms
495  Own<Clause> normalised = removeComplexTermsInAtoms(*cleaned);
496 
497  // swap if changed
498  if (*normalised != *clause) {
499  changed = true;
500  program.removeClause(clause);
501  program.addClause(std::move(normalised));
502  }
503  }
504 
505  return changed;
506 }
507 
508 } // namespace souffle::ast::transform

References clauses.


The documentation for this class was generated from the following files:
souffle::ast::cloneHead
Clause * cloneHead(const Clause *clause)
Returns a clause which contains head of the given clause.
Definition: Utils.cpp:254
souffle::ast::transform::ResolveAliasesTransformer::removeTrivialEquality
static Own< Clause > removeTrivialEquality(const Clause &clause)
Removes trivial equalities of the form t = t from the given clause.
Definition: ResolveAliases.cpp:368
souffle::ast::analysis::FunctorAnalysis::isMultiResult
static bool isMultiResult(const Functor &functor)
Definition: Functor.cpp:53
souffle::BinaryConstraintOp::EQ
@ EQ
souffle::map
auto map(const std::vector< A > &xs, F &&f)
Applies a function to each element of a vector and returns the results.
Definition: ContainerUtil.h:158
rhs
Own< Argument > rhs
Definition: ResolveAliases.cpp:185
lhs
Own< Argument > lhs
Definition: ResolveAliases.cpp:184
souffle::toString
const std::string & toString(const std::string &str)
A generic function converting strings into strings (trivial case).
Definition: StringUtil.h:234
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
i
size_t i
Definition: json11.h:663
clauses
std::vector< Own< Clause > > clauses
Definition: ComponentInstantiation.cpp:67
souffle::any_of
bool any_of(const Container &c, UnaryPredicate p)
A generic test checking whether any elements within a container satisfy a certain predicate.
Definition: FunctionalUtil.h:124
souffle::ast::getClauses
std::vector< Clause * > getClauses(const Program &program, const QualifiedName &relationName)
Returns a vector of clauses in the program describing the relation with the given name.
Definition: Utils.cpp:77
souffle::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
souffle::ast::transform::ResolveAliasesTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: ResolveAliases.cpp:479
souffle::ast::transform::ResolveAliasesTransformer::resolveAliases
static Own< Clause > resolveAliases(const Clause &clause)
Converts the given clause into a version without variables aliasing grounded variables.
Definition: ResolveAliases.cpp:214
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
rel
void rel(size_t limit, bool showLimit=true)
Definition: Tui.h:1086
souffle::ast::transform::ResolveAliasesTransformer::removeComplexTermsInAtoms
static Own< Clause > removeComplexTermsInAtoms(const Clause &clause)
Removes complex terms in atoms, replacing them with constrained variables.
Definition: ResolveAliases.cpp:389