souffle  2.0.2-371-g6315b36
ResolveAnonymousRecordAliases.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 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 ResolveAnonymousRecordAliases.cpp
12  *
13  ***********************************************************************/
14 
16 #include "ast/Argument.h"
17 #include "ast/BinaryConstraint.h"
18 #include "ast/BooleanConstraint.h"
19 #include "ast/Clause.h"
20 #include "ast/Literal.h"
21 #include "ast/Node.h"
22 #include "ast/Program.h"
23 #include "ast/RecordInit.h"
24 #include "ast/TranslationUnit.h"
25 #include "ast/UnnamedVariable.h"
26 #include "ast/Variable.h"
27 #include "ast/analysis/Ground.h"
28 #include "ast/analysis/Type.h"
30 #include "ast/utility/NodeMapper.h"
33 #include <map>
34 #include <memory>
35 #include <utility>
36 #include <vector>
37 
38 namespace souffle::ast::transform {
39 
40 std::map<std::string, const RecordInit*> ResolveAnonymousRecordAliasesTransformer::findVariablesRecordMapping(
41  TranslationUnit& tu, const Clause& clause) {
42  std::map<std::string, const RecordInit*> variableRecordMap;
43 
44  auto isVariable = [](Node* node) -> bool { return isA<ast::Variable>(node); };
45  auto isRecord = [](Node* node) -> bool { return isA<RecordInit>(node); };
46 
47  auto& typeAnalysis = *tu.getAnalysis<analysis::TypeAnalysis>();
48  auto groundedTerms = analysis::getGroundedTerms(tu, clause);
49 
50  for (auto* literal : clause.getBodyLiterals()) {
51  if (auto constraint = dynamic_cast<BinaryConstraint*>(literal)) {
52  if (!isEqConstraint(constraint->getBaseOperator())) {
53  continue;
54  }
55 
56  auto left = constraint->getLHS();
57  auto right = constraint->getRHS();
58 
59  if (!isVariable(left) && !isVariable(right)) {
60  continue;
61  }
62 
63  if (!isRecord(left) && !isRecord(right)) {
64  continue;
65  }
66 
67  // TODO (darth_tytus): This should change in the future.
68  // Currently type system assigns to anonymous records {- All types - }
69  // which is inelegant.
70  if (!typeAnalysis.getTypes(left).isAll()) {
71  continue;
72  }
73 
74  auto* variable = static_cast<ast::Variable*>(isVariable(left) ? left : right);
75  const auto& variableName = variable->getName();
76 
77  if (!groundedTerms.find(variable)->second) {
78  continue;
79  }
80 
81  // We are interested only in the first mapping.
82  if (variableRecordMap.find(variableName) != variableRecordMap.end()) {
83  continue;
84  }
85 
86  auto* record = static_cast<RecordInit*>(isRecord(left) ? left : right);
87 
88  variableRecordMap.insert({variableName, record});
89  }
90  }
91 
92  return variableRecordMap;
93 }
94 
95 bool ResolveAnonymousRecordAliasesTransformer::replaceNamedVariables(TranslationUnit& tu, Clause& clause) {
96  struct ReplaceVariables : public NodeMapper {
97  std::map<std::string, const RecordInit*> varToRecordMap;
98 
99  ReplaceVariables(std::map<std::string, const RecordInit*> varToRecordMap)
100  : varToRecordMap(std::move(varToRecordMap)){};
101 
102  Own<Node> operator()(Own<Node> node) const override {
103  if (auto variable = dynamic_cast<ast::Variable*>(node.get())) {
104  auto iteratorToRecord = varToRecordMap.find(variable->getName());
105  if (iteratorToRecord != varToRecordMap.end()) {
106  return souffle::clone(iteratorToRecord->second);
107  }
108  }
109 
110  node->apply(*this);
111 
112  return node;
113  }
114  };
115 
116  auto variableToRecordMap = findVariablesRecordMapping(tu, clause);
117  bool changed = variableToRecordMap.size() > 0;
118  if (changed) {
119  ReplaceVariables update(std::move(variableToRecordMap));
120  clause.apply(update);
121  }
122  return changed;
123 }
124 
126  struct ReplaceUnnamed : public NodeMapper {
127  mutable bool changed{false};
128  ReplaceUnnamed() = default;
129 
130  Own<Node> operator()(Own<Node> node) const override {
131  auto isUnnamed = [](Node* node) -> bool { return isA<UnnamedVariable>(node); };
132  auto isRecord = [](Node* node) -> bool { return isA<RecordInit>(node); };
133 
134  if (auto constraint = dynamic_cast<BinaryConstraint*>(node.get())) {
135  auto left = constraint->getLHS();
136  auto right = constraint->getRHS();
137  bool hasUnnamed = isUnnamed(left) || isUnnamed(right);
138  bool hasRecord = isRecord(left) || isRecord(right);
139  auto op = constraint->getBaseOperator();
140  if (hasUnnamed && hasRecord && isEqConstraint(op)) {
141  return mk<BooleanConstraint>(true);
142  }
143  }
144 
145  node->apply(*this);
146 
147  return node;
148  }
149  };
150 
151  ReplaceUnnamed update;
152  clause.apply(update);
153 
154  return update.changed;
155 }
156 
157 bool ResolveAnonymousRecordAliasesTransformer::transform(TranslationUnit& translationUnit) {
158  bool changed = false;
159  Program& program = translationUnit.getProgram();
160  for (auto* clause : program.getClauses()) {
161  changed |= replaceNamedVariables(translationUnit, *clause);
162  changed |= replaceUnnamedVariable(*clause);
163  }
164 
165  return changed;
166 }
167 
168 } // namespace souffle::ast::transform
BinaryConstraintOps.h
souffle::ast::transform::ResolveAnonymousRecordAliasesTransformer::replaceNamedVariables
bool replaceNamedVariables(TranslationUnit &, Clause &)
Use mapping found by findVariablesRecordMapping to substitute a records for each variable that operat...
Definition: ResolveAnonymousRecordAliases.cpp:99
TranslationUnit.h
UnnamedVariable.h
souffle::Own
std::unique_ptr< A > Own
Definition: ContainerUtil.h:42
MiscUtil.h
BooleanConstraint.h
souffle::ast::analysis::Variable
A variable to be utilized within constraints to be handled by the constraint solver.
Definition: ConstraintSystem.h:41
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
NodeMapper.h
Argument.h
Ground.h
souffle::clone
auto clone(const std::vector< A * > &xs)
Definition: ContainerUtil.h:172
Literal.h
souffle::ast::transform
Definition: Program.h:45
souffle::ast::transform::ResolveAnonymousRecordAliasesTransformer::transform
bool transform(TranslationUnit &translationUnit) override
Definition: ResolveAnonymousRecordAliases.cpp:161
ResolveAnonymousRecordAliases.h
souffle::isEqConstraint
bool isEqConstraint(const BinaryConstraintOp constraintOp)
Definition: BinaryConstraintOps.h:124
Node.h
souffle::ast::BinaryConstraint
Binary constraint class.
Definition: BinaryConstraint.h:53
souffle::ast::transform::ResolveAnonymousRecordAliasesTransformer::replaceUnnamedVariable
bool replaceUnnamedVariable(Clause &)
For unnamed variables, replace each equation _ op record with true.
Definition: ResolveAnonymousRecordAliases.cpp:129
souffle::ast::Node
Abstract class for syntactic elements in an input program.
Definition: Node.h:40
std
Definition: Brie.h:3053
Program.h
Clause.h
Type.h
souffle::ast::analysis::TypeAnalysis
Definition: Type.h:45
BinaryConstraint.h
souffle::ast::transform::ResolveAnonymousRecordAliasesTransformer::findVariablesRecordMapping
std::map< std::string, const RecordInit * > findVariablesRecordMapping(TranslationUnit &, const Clause &)
For each variable equal to some anonymous record, assign a value of that record.
Definition: ResolveAnonymousRecordAliases.cpp:44
RecordInit.h
Variable.h
TypeSystem.h