souffle  2.0.2-371-g6315b36
ast_utils_test.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, 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 ast_utils_test.cpp
12  *
13  * Tests souffle's AST utils.
14  *
15  ***********************************************************************/
16 
17 #include "tests/test.h"
18 
19 #include "ast/Argument.h"
20 #include "ast/Atom.h"
21 #include "ast/BinaryConstraint.h"
22 #include "ast/Clause.h"
23 #include "ast/Literal.h"
24 #include "ast/Negation.h"
25 #include "ast/Node.h"
26 #include "ast/Program.h"
27 #include "ast/QualifiedName.h"
28 #include "ast/Relation.h"
29 #include "ast/TranslationUnit.h"
30 #include "ast/Variable.h"
31 #include "ast/analysis/Ground.h"
32 #include "ast/utility/Utils.h"
33 #include "parser/ParserDriver.h"
34 #include "reports/DebugReport.h"
35 #include "reports/ErrorReport.h"
38 #include <algorithm>
39 #include <map>
40 #include <memory>
41 #include <string>
42 #include <utility>
43 #include <vector>
44 
45 namespace souffle::ast {
46 
47 namespace test {
48 
49 TEST(AstUtils, Grounded) {
50  // create an example clause:
51  auto clause = mk<Clause>();
52 
53  // something like:
54  // r(X,Y,Z) :- a(X), X = Y, !b(Z).
55 
56  // r(X,Y,Z)
57  auto* head = new Atom("r");
58  head->addArgument(Own<Argument>(new Variable("X")));
59  head->addArgument(Own<Argument>(new Variable("Y")));
60  head->addArgument(Own<Argument>(new Variable("Z")));
61  clause->setHead(Own<Atom>(head));
62 
63  // a(X)
64  auto* a = new Atom("a");
65  a->addArgument(Own<Argument>(new Variable("X")));
66  clause->addToBody(Own<Literal>(a));
67 
68  // X = Y
69  Literal* e1 = new BinaryConstraint(
71  clause->addToBody(Own<Literal>(e1));
72 
73  // !b(Z)
74  auto* b = new Atom("b");
75  b->addArgument(Own<Argument>(new Variable("Z")));
76  auto* neg = new Negation(Own<Atom>(b));
77  clause->addToBody(Own<Literal>(neg));
78 
79  // check construction
80  EXPECT_EQ("r(X,Y,Z) :- \n a(X),\n X = Y,\n !b(Z).", toString(*clause));
81 
82  auto program = mk<Program>();
83  program->addClause(std::move(clause));
84  DebugReport dbgReport;
85  ErrorReport errReport;
86  TranslationUnit tu{std::move(program), errReport, dbgReport};
87 
88  // obtain groundness
89  auto isGrounded = analysis::getGroundedTerms(tu, *tu.getProgram().getClauses()[0]);
90 
91  auto args = head->getArguments();
92  // check selected sub-terms
93  EXPECT_TRUE(isGrounded[args[0]]); // X
94  EXPECT_TRUE(isGrounded[args[1]]); // Y
95  EXPECT_FALSE(isGrounded[args[2]]); // Z
96 }
97 
98 TEST(AstUtils, GroundedRecords) {
99  ErrorReport e;
100  DebugReport d;
102  R"(
103  .type N <: symbol
104  .type R = [ a : N, B : N ]
105 
106  .decl r ( r : R )
107  .decl s ( r : N )
108 
109  s(x) :- r([x,y]).
110 
111  )",
112  e, d);
113 
114  Program& program = tu->getProgram();
115 
116  Clause* clause = getClauses(program, "s")[0];
117 
118  // check construction
119  EXPECT_EQ("s(x) :- \n r([x,y]).", toString(*clause));
120 
121  // obtain groundness
122  auto isGrounded = analysis::getGroundedTerms(*tu, *clause);
123 
124  const Atom* s = clause->getHead();
125  const auto* r = dynamic_cast<const Atom*>(clause->getBodyLiterals()[0]);
126 
127  EXPECT_TRUE(s);
128  EXPECT_TRUE(r);
129 
130  // check selected sub-terms
131  EXPECT_TRUE(isGrounded[s->getArguments()[0]]);
132  EXPECT_TRUE(isGrounded[r->getArguments()[0]]);
133 }
134 
135 TEST(AstUtils, ReorderClauseAtoms) {
136  ErrorReport e;
137  DebugReport d;
138 
140  R"(
141  .decl a,b,c,d,e(x:number)
142  a(x) :- b(x), c(x), 1 != 2, d(y), !e(z), c(z), e(x).
143  .output a()
144  )",
145  e, d);
146 
147  Program& program = tu->getProgram();
148  EXPECT_EQ(5, program.getRelations().size());
149 
150  Relation* a = getRelation(program, "a");
151  EXPECT_NE(a, nullptr);
152  const auto& clauses = getClauses(program, *a);
153  EXPECT_EQ(1, clauses.size());
154 
155  Clause* clause = clauses[0];
156  EXPECT_EQ("a(x) :- \n b(x),\n c(x),\n 1 != 2,\n d(y),\n !e(z),\n c(z),\n e(x).",
157  toString(*clause));
158 
159  // Check trivial permutation
160  Own<Clause> reorderedClause0 =
161  Own<Clause>(reorderAtoms(clause, std::vector<unsigned int>({0, 1, 2, 3, 4})));
162  EXPECT_EQ("a(x) :- \n b(x),\n c(x),\n 1 != 2,\n d(y),\n !e(z),\n c(z),\n e(x).",
163  toString(*reorderedClause0));
164 
165  // Check more complex permutation
166  Own<Clause> reorderedClause1 =
167  Own<Clause>(reorderAtoms(clause, std::vector<unsigned int>({2, 3, 4, 1, 0})));
168  EXPECT_EQ("a(x) :- \n d(y),\n c(z),\n 1 != 2,\n e(x),\n !e(z),\n c(x),\n b(x).",
169  toString(*reorderedClause1));
170 }
171 
172 } // namespace test
173 } // namespace souffle::ast
BinaryConstraintOps.h
souffle::ParserDriver::parseTranslationUnit
static Own< ast::TranslationUnit > parseTranslationUnit(const std::string &filename, FILE *in, ErrorReport &errorReport, DebugReport &debugReport)
Definition: ParserDriver.cpp:84
EXPECT_TRUE
#define EXPECT_TRUE(a)
Definition: test.h:189
TranslationUnit.h
souffle::ast::Atom::getArguments
std::vector< Argument * > getArguments() const
Return arguments.
Definition: Atom.h:77
DebugReport.h
souffle::ast::reorderAtoms
Clause * reorderAtoms(const Clause *clause, const std::vector< unsigned int > &newOrder)
Reorders the atoms of a clause to be in the given order.
Definition: Utils.cpp:264
souffle::ast::test::TEST
TEST(RuleBody, Basic)
Definition: ast_parser_utils_test.cpp:46
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: test.h:191
e
l j a showGridBackground &&c b raw series this eventEmitter e
Definition: htmlJsChartistMin.h:15
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
souffle::BinaryConstraintOp::EQ
@ EQ
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::Variable
A variable to be utilized within constraints to be handled by the constraint solver.
Definition: ConstraintSystem.h:41
Relation.h
souffle::ast::Atom
An atom class.
Definition: Atom.h:51
souffle::ast::Clause::getHead
Atom * getHead() const
Return the atom that represents the head of the clause.
Definition: Clause.h:74
souffle::ast::analysis::getGroundedTerms
std::map< const Argument *, bool > getGroundedTerms(const TranslationUnit &tu, const Clause &clause)
Analyse the given clause and computes for each contained argument whether it is a grounded value or n...
Definition: Ground.cpp:278
Utils.h
souffle::toString
const std::string & toString(const std::string &str)
A generic function converting strings into strings (trivial case).
Definition: StringUtil.h:234
Argument.h
souffle::ast::Program
The program class consists of relations, clauses and types.
Definition: Program.h:52
Ground.h
souffle::ast::getRelation
Relation * getRelation(const Program &program, const QualifiedName &name)
Returns the relation with the given name in the program.
Definition: Utils.cpp:101
souffle::DebugReport
Class representing a HTML report, consisting of a list of sections.
Definition: DebugReport.h:87
souffle::ast::Negation
Negation of an atom negated atom.
Definition: Negation.h:50
clauses
std::vector< Own< Clause > > clauses
Definition: ComponentInstantiation.cpp:67
StringUtil.h
Atom.h
Literal.h
souffle::ast::TranslationUnit
Translation unit class for the translation pipeline.
Definition: TranslationUnit.h:51
souffle::ast::Literal
Defines an abstract class for literals in a horn clause.
Definition: Literal.h:36
souffle::ast::Program::getRelations
std::vector< Relation * > getRelations() const
Return relations.
Definition: Program.h:60
test.h
Negation.h
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
Node.h
EXPECT_NE
#define EXPECT_NE(a, b)
Definition: test.h:195
souffle::ast::BinaryConstraint
Binary constraint class.
Definition: BinaryConstraint.h:53
QualifiedName.h
b
l j a showGridBackground &&c b raw series this eventEmitter b
Definition: htmlJsChartistMin.h:15
Program.h
Clause.h
d
else d
Definition: htmlJsChartistMin.h:15
ParserDriver.h
BinaryConstraint.h
souffle::ast
Definition: Aggregator.h:35
souffle::ErrorReport
Definition: ErrorReport.h:152
ErrorReport.h
EXPECT_FALSE
#define EXPECT_FALSE(a)
Definition: test.h:190
souffle::ast::Clause::getBodyLiterals
std::vector< Literal * > getBodyLiterals() const
Obtains a copy of the internally maintained body literals.
Definition: Clause.h:79
Variable.h