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;