52 struct InstantiateUnnamedVariables :
public NodeMapper {
55 if (isA<UnnamedVariable>(node.get())) {
58 if (isA<Aggregator>(node.get())) {
67 InstantiateUnnamedVariables update;
68 for (
const auto& lit : aggClause.getBodyLiterals()) {
74 const TranslationUnit& tu,
const Clause& clause,
const Aggregator& aggregate) {
88 std::set<std::string> headArguments;
91 headArguments.insert(localVarName);
95 if (aggregate == innerAggregate) {
99 headArguments.erase(innerLocalVariableName);
104 headArguments.insert(injectedVarName);
106 return headArguments;
111 const TranslationUnit& translationUnit, Clause& aggClause,
const Clause& originalClause,
112 const Aggregator& aggregate) {
116 struct NegateAggregateAtoms :
public NodeMapper {
117 std::unique_ptr<Node> operator()(std::unique_ptr<Node> node)
const override {
118 if (
auto* aggregate =
dynamic_cast<Aggregator*
>(node.get())) {
124 std::vector<Own<Literal>> newBody;
125 for (
const auto& lit : aggregate->getBodyLiterals()) {
126 if (
auto* atom =
dynamic_cast<Atom*
>(lit)) {
130 aggregate->setBody(std::move(newBody));
138 aggClauseInnerAggregatesMasked->setHead(mk<Atom>(
"*"));
139 NegateAggregateAtoms update;
140 aggClauseInnerAggregatesMasked->apply(update);
143 std::set<std::string> injectedVariables =
146 std::set<std::string> alreadyGrounded;
148 const auto* variable =
dynamic_cast<const ast::Variable*
>(argPair.first);
149 bool variableIsGrounded = argPair.second;
150 if (variable ==
nullptr || variableIsGrounded) {
154 if (injectedVariables.find(variable->getName()) == injectedVariables.end()) {
158 std::string ungroundedVariableName = variable->getName();
159 if (alreadyGrounded.find(ungroundedVariableName) != alreadyGrounded.end()) {
165 for (
const auto& lit : originalClause.getBodyLiterals()) {
167 bool originalAggregateFound =
false;
169 if (a == aggregate) {
170 originalAggregateFound =
true;
174 if (originalAggregateFound) {
178 if (alreadyGrounded.find(ungroundedVariableName) != alreadyGrounded.end()) {
182 bool variableOccursInLit =
false;
184 if (var.getName() == ungroundedVariableName) {
185 variableOccursInLit = true;
188 if (!variableOccursInLit) {
192 auto singleLiteralClause = mk<Clause>();
194 bool variableGroundedByLiteral =
false;
196 const auto* var =
dynamic_cast<const ast::Variable*
>(argPair.first);
197 if (var ==
nullptr) {
200 bool isGrounded = argPair.second;
201 if (var->getName() == ungroundedVariableName && isGrounded) {
202 variableGroundedByLiteral =
true;
205 if (!variableGroundedByLiteral) {
212 if (
const auto* atom =
dynamic_cast<const Atom*
>(lit)) {
219 VecOwn<Argument> arguments;
220 for (
auto arg : atom->getArguments()) {
221 if (
auto* var =
dynamic_cast<ast::Variable*
>(arg)) {
222 if (var->getName() == ungroundedVariableName) {
223 arguments.emplace_back(arg->clone());
227 arguments.emplace_back(
new UnnamedVariable());
231 mk<Atom>(atom->getQualifiedName(), std::move(arguments), atom->getSrcLoc());
233 alreadyGrounded.insert(ungroundedVariableName);
236 assert(alreadyGrounded.find(ungroundedVariableName) != alreadyGrounded.end() &&
237 "Error: Unable to ground parameter in materialisation-requiring aggregate body");
246 TranslationUnit& translationUnit) {
247 bool changed =
false;
248 Program& program = translationUnit.getProgram();
262 std::set<const Aggregator*> innerAggregates;
265 if (agg != innerAgg) {
266 innerAggregates.insert(&innerAgg);
277 if (innerAggregates.find(&agg) != innerAggregates.end()) {
282 auto aggClause = mk<Clause>();
285 aggClause->addToBody(souffle::clone(lit));
288 instantiateUnnamedVariables(*aggClause);
295 auto* aggClauseHead =
new Atom(aggregateBodyRelationName);
298 for (
const auto& variableName : headArguments) {
299 aggClauseHead->addArgument(mk<Variable>(variableName));
301 aggClause->setHead(
Own<Atom>(aggClauseHead));
303 auto aggRel = mk<Relation>(aggregateBodyRelationName);
304 std::map<const Argument*, analysis::TypeSet> argTypes =
307 for (
const auto& cur : aggClauseHead->getArguments()) {
310 aggRel->addAttribute(mk<Attribute>(
toString(*cur),
322 const auto* targetExpressionVariable =
324 localVariables.erase(targetExpressionVariable->getName());
326 VecOwn<Argument> args;
327 for (
auto arg : aggClauseHead->getArguments()) {
328 if (
auto* var =
dynamic_cast<ast::Variable*
>(arg)) {
331 if (localVariables.find(var->getName()) != localVariables.end()) {
332 args.emplace_back(
new UnnamedVariable());
336 args.emplace_back(arg->clone());
339 mk<Atom>(aggClauseHead->getQualifiedName(), std::move(args), aggClauseHead->getSrcLoc());
341 VecOwn<Literal> newBody;
342 newBody.push_back(std::move(aggAtom));
343 const_cast<Aggregator&
>(agg).setBody(std::move(newBody));
345 program.addClause(std::move(aggClause));
346 program.addRelation(std::move(aggRel));
356 const Atom* atom =
nullptr;
357 for (
const auto& literal : agg.getBodyLiterals()) {
358 const Atom* currentAtom =
dynamic_cast<const Atom*
>(literal);
359 if (currentAtom !=
nullptr) {
365 if (countAtoms > 1) {
369 bool seenInnerAggregate =
false;
372 if (agg != innerAgg) {
373 seenInnerAggregate =
true;
377 if (seenInnerAggregate) {
382 bool duplicates =
false;
383 std::set<std::string> vars;
384 if (atom !=
nullptr) {
386 duplicates = duplicates || !vars.insert(var.getName()).second;