souffle  2.0.2-371-g6315b36
RecursiveClauses.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file RecursiveClauses.cpp
12  *
13  * Implements method of precedence graph to build the precedence graph,
14  * compute strongly connected components of the precedence graph, and
15  * build the strongly connected component graph.
16  *
17  ***********************************************************************/
18 
20 #include "ast/Atom.h"
21 #include "ast/Clause.h"
22 #include "ast/Node.h"
23 #include "ast/Program.h"
24 #include "ast/Relation.h"
25 #include "ast/TranslationUnit.h"
27 #include "ast/utility/Utils.h"
28 #include "ast/utility/Visitor.h"
30 #include <algorithm>
31 #include <set>
32 #include <utility>
33 #include <vector>
34 
35 namespace souffle::ast::analysis {
36 
37 void RecursiveClausesAnalysis::run(const TranslationUnit& translationUnit) {
38  Program& program = translationUnit.getProgram();
39  visitDepthFirst(program, [&](const Clause& clause) {
40  if (computeIsRecursive(clause, translationUnit)) {
41  recursiveClauses.insert(&clause);
42  }
43  });
44 }
45 
46 void RecursiveClausesAnalysis::print(std::ostream& os) const {
47  os << recursiveClauses << std::endl;
48 }
49 
51  const Clause& clause, const TranslationUnit& translationUnit) const {
52  const auto& relationDetail = *translationUnit.getAnalysis<RelationDetailCacheAnalysis>();
53  const Program& program = translationUnit.getProgram();
54 
55  // we want to reach the atom of the head through the body
56  const Relation* trg = getHeadRelation(&clause, &program);
57 
58  std::set<const Relation*> reached;
59  std::vector<const Relation*> worklist;
60 
61  // set up start list
62  for (const auto* cur : getBodyLiterals<Atom>(clause)) {
63  auto rel = relationDetail.getRelation(cur->getQualifiedName());
64  if (rel == trg) {
65  return true;
66  }
67  worklist.push_back(rel);
68  }
69 
70  // process remaining elements
71  while (!worklist.empty()) {
72  // get next to process
73  const Relation* cur = worklist.back();
74  worklist.pop_back();
75 
76  // skip null pointers (errors in the input code)
77  if (cur == nullptr) {
78  continue;
79  }
80 
81  // check whether this one has been checked before
82  if (!reached.insert(cur).second) {
83  continue;
84  }
85 
86  // check all atoms in the relations
87  for (const Clause* cl : relationDetail.getClauses(cur)) {
88  for (const Atom* at : getBodyLiterals<Atom>(*cl)) {
89  auto rel = relationDetail.getRelation(at->getQualifiedName());
90  if (rel == trg) {
91  return true;
92  }
93  worklist.push_back(rel);
94  }
95  }
96  }
97 
98  // no cycles found
99  return false;
100 }
101 
102 } // namespace souffle::ast::analysis
TranslationUnit.h
RecursiveClauses.h
souffle::ast::analysis::RecursiveClausesAnalysis::run
void run(const TranslationUnit &translationUnit) override
run analysis for a Ast translation unit
Definition: RecursiveClauses.cpp:45
RelationDetailCache.h
souffle::ast::Relation
Defines a relation with a name, attributes, qualifiers, and internal representation.
Definition: Relation.h:49
souffle::ast::Clause
Intermediate representation of a horn clause.
Definition: Clause.h:51
souffle::ast::analysis::RecursiveClausesAnalysis::computeIsRecursive
bool computeIsRecursive(const Clause &clause, const TranslationUnit &translationUnit) const
Determines whether the given clause is recursive within the given program.
Definition: RecursiveClauses.cpp:58
souffle::ast::analysis::RelationDetailCacheAnalysis
Analysis pass mapping identifiers with relations and clauses.
Definition: RelationDetailCache.h:47
Relation.h
Utils.h
souffle::ast::Program
The program class consists of relations, clauses and types.
Definition: Program.h:52
souffle::ast::analysis::RecursiveClausesAnalysis::recursiveClauses
std::set< const Clause * > recursiveClauses
Definition: RecursiveClauses.h:59
souffle::ast::analysis::RecursiveClausesAnalysis::print
void print(std::ostream &os) const override
print the analysis result in HTML format
Definition: RecursiveClauses.cpp:54
Atom.h
souffle::ast::TranslationUnit
Translation unit class for the translation pipeline.
Definition: TranslationUnit.h:51
souffle::ast::getHeadRelation
const Relation * getHeadRelation(const Clause *clause, const Program *program)
Returns the relation referenced by the head of the given clause.
Definition: Utils.cpp:133
Node.h
souffle::ast::TranslationUnit::getAnalysis
Analysis * getAnalysis() const
get analysis: analysis is generated on the fly if not present
Definition: TranslationUnit.h:60
Program.h
StreamUtil.h
Visitor.h
Clause.h
souffle::ast::analysis
Definition: Aggregate.cpp:39
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::TranslationUnit::getProgram
Program & getProgram() const
Return the program.
Definition: TranslationUnit.h:84