diff --git a/src/ast2ram/AstToRamTranslator.cpp b/src/ast2ram/AstToRamTranslator.cpp index 2862755262b..a65a3a2777c 100644 --- a/src/ast2ram/AstToRamTranslator.cpp +++ b/src/ast2ram/AstToRamTranslator.cpp @@ -524,33 +524,46 @@ VecOwn AstToRamTranslator::generateStratumMainLoop( return loopSeq; } -/** generate RAM code for recursive relations in a strongly-connected component */ -Own AstToRamTranslator::translateRecursiveRelation( - const std::set& scc) { - // -- Initialise all the individual sections -- - auto preamble = generateStratumPreamble(scc); - auto loopSeq = generateStratumMainLoop(scc); - auto updateTable = generateStratumTableUpdates(scc); - auto postamble = generateStratumPostamble(scc); - - // --- Combine the individual sections into the final fixpoint loop -- - // Construct exit conditions for odd and even iteration - auto addCondition = [](Own& cond, Own clause) { - cond = ((cond) ? mk(std::move(cond), std::move(clause)) : std::move(clause)); +VecOwn AstToRamTranslator::generateStratumExitConditions( + const std::set& scc) const { + // Helper function to add a new term to a conjunctive condition + auto addCondition = [&](Own& cond, Own term) { + cond = (cond == nullptr) ? std::move(term) : mk(std::move(cond), std::move(term)); }; - Own exitCond; - VecOwn exitStmts; + VecOwn exitConditions; + + // (1) if all relations in the scc are empty + Own emptinessCheck; + for (const ast::Relation* rel : scc) { + addCondition(emptinessCheck, mk(getNewRelationName(rel))); + } + appendStmt(exitConditions, mk(std::move(emptinessCheck))); + + // (2) if the size limit has been reached for any limitsize relations for (const ast::Relation* rel : scc) { - addCondition(exitCond, mk(getNewRelationName(rel))); if (ioType->isLimitSize(rel)) { Own limit = mk(BinaryConstraintOp::GE, mk(getConcreteRelationName(rel)), mk(ioType->getLimitSize(rel))); - appendStmt(exitStmts, mk(std::move(limit))); + appendStmt(exitConditions, mk(std::move(limit))); } } + return exitConditions; +} + +/** generate RAM code for recursive relations in a strongly-connected component */ +Own AstToRamTranslator::translateRecursiveRelation( + const std::set& scc) { + // -- Initialise all the individual sections -- + auto preamble = generateStratumPreamble(scc); + auto loopSeq = generateStratumMainLoop(scc); + auto updateTable = generateStratumTableUpdates(scc); + auto exitConditions = generateStratumExitConditions(scc); + auto postamble = generateStratumPostamble(scc); + + // --- Combine the individual sections into the final fixpoint loop -- VecOwn res; // Add in the preamble @@ -560,12 +573,11 @@ Own AstToRamTranslator::translateRecursiveRelation( // Add in the main loop and update sections auto loop = mk(std::move(loopSeq)); - if (!loop->getStatements().empty() && exitCond && !updateTable.empty()) { - auto ramExitCondition = mk(std::move(exitCond)); - auto ramExitSequence = mk(std::move(exitStmts)); + if (!loop->getStatements().empty() && !exitConditions.empty() && !updateTable.empty()) { + auto ramExitSequence = mk(std::move(exitConditions)); auto ramUpdateSequence = mk(std::move(updateTable)); - auto ramLoopSequence = mk(mk(std::move(loop), std::move(ramExitCondition), - std::move(ramExitSequence), std::move(ramUpdateSequence))); + auto ramLoopSequence = mk( + mk(std::move(loop), std::move(ramExitSequence), std::move(ramUpdateSequence))); appendStmt(res, std::move(ramLoopSequence)); } diff --git a/src/ast2ram/AstToRamTranslator.h b/src/ast2ram/AstToRamTranslator.h index 096f83744ea..f3b42275d5b 100644 --- a/src/ast2ram/AstToRamTranslator.h +++ b/src/ast2ram/AstToRamTranslator.h @@ -166,6 +166,7 @@ class AstToRamTranslator { VecOwn generateStratumPostamble(const std::set& scc) const; VecOwn generateStratumTableUpdates(const std::set& scc) const; VecOwn generateStratumMainLoop(const std::set& scc); + VecOwn generateStratumExitConditions(const std::set& scc) const; }; } // namespace souffle::ast2ram