140         stmtList.push_back(std::move(stmt));
 
  165         const ast::Relation* 
rel) {
 
  166     std::vector<std::map<std::string, std::string>> inputDirectives;
 
  169         if (load->getQualifiedName() != 
rel->getQualifiedName() ||
 
  174         std::map<std::string, std::string> 
directives;
 
  175         for (
const auto& currentPair : load->getParameters()) {
 
  181     if (inputDirectives.empty()) {
 
  182         inputDirectives.emplace_back();
 
  185     return inputDirectives;
 
  189         const ast::Relation* 
rel) {
 
  190     std::vector<std::map<std::string, std::string>> outputDirectives;
 
  193         if (store->getQualifiedName() != 
rel->getQualifiedName() ||
 
  199         std::map<std::string, std::string> 
directives;
 
  200         for (
const auto& currentPair : store->getParameters()) {
 
  206     if (outputDirectives.empty()) {
 
  207         outputDirectives.emplace_back();
 
  210     return outputDirectives;
 
  218         const ast::Relation* 
rel, 
const std::string relationNamePrefix) {
 
  231     if (arg == 
nullptr) {
 
  235     class ValueTranslator : 
public ast::Visitor<Own<ram::Expression>> {
 
  246             if (!index.
isDefined(var)) 
fatal(
"variable `%s` is not grounded", var);
 
  251             return mk<ram::UndefValue>();
 
  254         Own<ram::Expression> visitNumericConstant(
const ast::NumericConstant& c)
 override {
 
  255             assert(c.getFinalType().has_value() && 
"constant should have valid type");
 
  256             switch (c.getFinalType().value()) {
 
  265             fatal(
"unexpected numeric constant type");
 
  268         Own<ram::Expression> visitStringConstant(
const ast::StringConstant& c)
 override {
 
  272         Own<ram::Expression> visitNilConstant(
const ast::NilConstant&)
 override {
 
  273             return mk<ram::SignedConstant>(0);
 
  276         Own<ram::Expression> visitTypeCast(
const ast::TypeCast& typeCast)
 override {
 
  280         Own<ram::Expression> visitIntrinsicFunctor(
const ast::IntrinsicFunctor& inf)
 override {
 
  281             VecOwn<ram::Expression> values;
 
  282             for (
const auto& cur : inf.getArguments()) {
 
  289                 return mk<ram::IntrinsicOperator>(inf.getFinalOpType().value(), std::move(values));
 
  293         Own<ram::Expression> visitUserDefinedFunctor(
const ast::UserDefinedFunctor& udf)
 override {
 
  294             VecOwn<ram::Expression> values;
 
  295             for (
const auto& cur : udf.getArguments()) {
 
  300             return mk<ram::UserDefinedOperator>(udf.getName(), argTypes, returnType,
 
  304         Own<ram::Expression> visitCounter(
const ast::Counter&)
 override {
 
  305             return mk<ram::AutoIncrement>();
 
  308         Own<ram::Expression> visitRecordInit(
const ast::RecordInit& init)
 override {
 
  309             VecOwn<ram::Expression> values;
 
  310             for (
const auto& cur : init.getArguments()) {
 
  313             return mk<ram::PackRecord>(std::move(values));
 
  316         Own<ram::Expression> visitAggregator(
const ast::Aggregator& agg)
 override {
 
  321         Own<ram::Expression> visitSubroutineArgument(
const ast::SubroutineArgument& subArg)
 override {
 
  322             return mk<ram::SubroutineArgument>(subArg.getNumber());
 
  326     return ValueTranslator(*
this, index, 
polyAnalysis)(*arg);
 
  330     static SymbolTable symbolTable;
 
  336     class ConstraintTranslator : 
public ast::Visitor<Own<ram::Condition>> {
 
  353             assert(binRel.
getFinalType().has_value() && 
"binary constraint has unset type");
 
  356             return mk<ram::Constraint>(binRel.
getFinalType().value(), std::move(valLHS), std::move(valRHS));
 
  360         Own<ram::Condition> visitProvenanceNegation(
const ast::ProvenanceNegation& neg)
 override {
 
  361             const auto* atom = neg.getAtom();
 
  363             assert(auxiliaryArity <= atom->getArity() && 
"auxiliary arity out of bounds");
 
  364             size_t arity = atom->
getArity() - auxiliaryArity;
 
  365             VecOwn<ram::Expression> values;
 
  368             for (
size_t i = 0; 
i < arity; 
i++) {
 
  374                 values.push_back(mk<ram::UndefValue>());
 
  376                 for (
size_t height = 1; height < auxiliaryArity; height++) {
 
  377                     values.push_back(translator.
translateValue(args[arity + height], index));
 
  380             return mk<ram::Negation>(
 
  381                     mk<ram::ProvenanceExistenceCheck>(translator.
translateRelation(atom), std::move(values)));
 
  385         Own<ram::Condition> visitNegation(
const ast::Negation& neg)
 override {
 
  386             const auto* atom = neg.getAtom();
 
  388             assert(auxiliaryArity <= atom->getArity() && 
"auxiliary arity out of bounds");
 
  389             size_t arity = atom->
getArity() - auxiliaryArity;
 
  397             VecOwn<ram::Expression> values;
 
  399             for (
size_t i = 0; 
i < arity; 
i++) {
 
  402             for (
size_t i = 0; 
i < auxiliaryArity; 
i++) {
 
  403                 values.push_back(mk<ram::UndefValue>());
 
  405             return mk<ram::Negation>(
 
  409     return ConstraintTranslator(*
this, index, 
polyAnalysis)(*lit);
 
  413     if (
auto strConstant = 
dynamic_cast<const ast::StringConstant*
>(&constant)) {
 
  415     } 
else if (isA<ast::NilConstant>(&constant)) {
 
  417     } 
else if (
auto* numConstant = 
dynamic_cast<const ast::NumericConstant*
>(&constant)) {
 
  418         assert(numConstant->getFinalType().has_value() && 
"constant should have valid type");
 
  419         switch (numConstant->getFinalType().value()) {
 
  428     fatal(
"unaccounted-for constant");
 
  434     if (
auto* 
const c_num = 
dynamic_cast<const ast::NumericConstant*
>(&c)) {
 
  435         switch (c_num->getFinalType().value()) {
 
  442     return mk<ram::SignedConstant>(rawConstant);
 
  447         const ast::Relation& 
rel, 
const ast::analysis::RecursiveClausesAnalysis* recursiveClauses) {
 
  449     VecOwn<ram::Statement> res;
 
  456         if (recursiveClauses->recursive(clause)) {
 
  465             const std::string& relationName = 
toString(
rel.getQualifiedName());
 
  466             const SrcLocation& srcLocation = clause->getSrcLoc();
 
  468             const std::string logTimerStatement =
 
  470             const std::string logSizeStatement =
 
  472             rule = mk<ram::LogRelationTimer>(std::move(
rule), logTimerStatement, relName);
 
  476         std::ostringstream ds;
 
  477         ds << 
toString(*clause) << 
"\nin file ";
 
  478         ds << clause->getSrcLoc();
 
  479         rule = mk<ram::DebugInfo>(std::move(
rule), ds.str());
 
  487         const std::string& relationName = 
toString(
rel.getQualifiedName());
 
  493             const std::string logTimerStatement =
 
  496                     mk<ram::LogRelationTimer>(mk<ram::Sequence>(std::move(res)), logTimerStatement, relName);
 
  501             appendStmt(res, mk<ram::LogSize>(relName, logSizeStatement));
 
  506     return mk<ram::Sequence>(std::move(res));
 
  515     struct Instantiator : 
public ast::NodeMapper {
 
  516         mutable int counter = 0;
 
  518         Instantiator() = 
default;
 
  526                 auto name = 
" _unnamed_var" + 
toString(++counter);
 
  527                 return mk<ast::Variable>(name);
 
  537     for (
auto& atom : ast::getBodyLiterals<ast::Atom>(*clause)) {
 
  558         if (
rel->getArity() == 0) {
 
  559             return mk<ram::Query>(mk<ram::Filter>(mk<ram::Negation>(mk<ram::EmptinessCheck>(srcRel)),
 
  560                     mk<ram::Project>(destRel, std::move(values))));
 
  562         for (std::size_t 
i = 0; 
i < 
rel->getArity(); 
i++) {
 
  563             values.push_back(mk<ram::TupleElement>(0, 
i));
 
  565         auto stmt = mk<ram::Query>(mk<ram::Scan>(srcRel, 0, mk<ram::Project>(destRel, std::move(values))));
 
  567             return mk<ram::Sequence>(mk<ram::Extend>(destRel, srcRel), std::move(stmt));
 
  585             updateRelTable = mk<ram::LogRelationTimer>(std::move(updateRelTable),
 
  600         appendStmt(updateTable, std::move(updateRelTable));
 
  605     VecOwn<ram::Statement> loopSeq;
 
  608     auto isInSameSCC = [&](
const ast::Relation* 
rel) {
 
  609         return std::find(scc.begin(), scc.end(), 
rel) != scc.end();
 
  613     for (
const ast::Relation* 
rel : scc) {
 
  614         VecOwn<ram::Statement> loopRelSeq;
 
  625             const auto& atoms = ast::getBodyLiterals<ast::Atom>(*cl);
 
  626             for (
size_t j = 0; 
j < atoms.size(); ++
j) {
 
  627                 const ast::Atom* atom = atoms[
j];
 
  631                 if (!isInSameSCC(atomRelation)) {
 
  636                 Own<ast::Clause> r1(cl->clone());
 
  638                 ast::getBodyLiterals<ast::Atom>(*r1)[
j]->setQualifiedName(
 
  641                     r1->addToBody(mk<ast::ProvenanceNegation>(
souffle::clone(cl->getHead())));
 
  643                     if (r1->getHead()->getArity() > 0) {
 
  653                 for (
size_t k = 
j + 1; 
k < atoms.size(); 
k++) {
 
  657                         r1->addToBody(mk<ast::Negation>(std::move(cur)));
 
  661                 Own<ram::Statement> 
rule = ClauseTranslator(*this).translateClause(*r1, *cl, version);
 
  665                     const std::string& relationName = 
toString(
rel->getQualifiedName());
 
  666                     const SrcLocation& srcLocation = cl->getSrcLoc();
 
  668                     const std::string logTimerStatement =
 
  670                     const std::string logSizeStatement =
 
  672                     rule = mk<ram::LogRelationTimer>(
 
  677                 std::ostringstream ds;
 
  678                 ds << 
toString(*cl) << 
"\nin file ";
 
  679                 ds << cl->getSrcLoc();
 
  680                 rule = mk<ram::DebugInfo>(std::move(
rule), ds.str());
 
  689             if (cl->getExecutionPlan() != 
nullptr) {
 
  692                 for (
auto const& cur : cl->getExecutionPlan()->getOrders()) {
 
  693                     maxVersion = std::max(cur.first, maxVersion);
 
  695                 assert(version > maxVersion && 
"missing clause versions");
 
  700         if (loopRelSeq.size() == 0) {
 
  706             const std::string& relationName = 
toString(
rel->getQualifiedName());
 
  707             const SrcLocation& srcLocation = 
rel->getSrcLoc();
 
  710             auto newStmt = mk<ram::LogRelationTimer>(
 
  717         appendStmt(loopSeq, mk<ram::Sequence>(std::move(loopRelSeq)));
 
  719     auto loop = mk<ram::Parallel>(std::move(loopSeq));
 
  722     auto addCondition = [](Own<ram::Condition>& cond, Own<ram::Condition> clause) {
 
  723         cond = ((cond) ? mk<ram::Conjunction>(std::move(cond), std::move(clause)) : std::move(clause));
 
  726     Own<ram::Condition> exitCond;
 
  727     VecOwn<ram::Statement> exitStmts;
 
  728     for (
const ast::Relation* 
rel : scc) {
 
  731             Own<ram::Condition> limit =
 
  734             appendStmt(exitStmts, mk<ram::Exit>(std::move(limit)));
 
  739     VecOwn<ram::Statement> res;
 
  740     if (preamble.size() > 0) {
 
  741         appendStmt(res, mk<ram::Sequence>(std::move(preamble)));
 
  743     if (!loop->getStatements().empty() && exitCond && updateTable.size() > 0) {
 
  745                 mk<ram::Loop>(mk<ram::Sequence>(std::move(loop), mk<ram::Exit>(std::move(exitCond)),
 
  746                         mk<ram::Sequence>(std::move(exitStmts)), mk<ram::Sequence>(std::move(updateTable)))));
 
  748     if (postamble.size() > 0) {
 
  749         appendStmt(res, mk<ram::Sequence>(std::move(postamble)));
 
  751     if (res.size() > 0) {
 
  752         return mk<ram::Sequence>(std::move(res));
 
  755     fatal(
"Not Implemented");
 
  760     auto intermediateClause = mk<ast::Clause>(
souffle::clone(clause.getHead()));
 
  763     for (
auto bodyLit : clause.getBodyLiterals()) {
 
  765         if (!isA<ast::Constraint>(bodyLit)) {
 
  771     for (
auto bodyLit : ast::getBodyLiterals<ast::Constraint>(clause)) {
 
  779     ast::Atom* head = intermediateClause->getHead();
 
  781     auto args = head->getArguments();
 
  782     for (
size_t i = 0; 
i < head->getArity() - auxiliaryArity; 
i++) {
 
  785         if (
auto var = 
dynamic_cast<ast::Variable*
>(arg)) {
 
  787             auto constraint = mk<ast::BinaryConstraint>(
 
  790             intermediateClause->addToBody(std::move(constraint));
 
  791         } 
else if (
auto func = 
dynamic_cast<ast::Functor*
>(arg)) {
 
  793             if (
auto* inf = 
dynamic_cast<ast::IntrinsicFunctor*
>(func)) {
 
  794                 assert(inf->getFinalReturnType().has_value() && 
"functor has missing return type");
 
  795                 returnType = inf->getFinalReturnType().value();
 
  796             } 
else if (
auto* udf = 
dynamic_cast<ast::UserDefinedFunctor*
>(func)) {
 
  797                 assert(udf->getFinalReturnType().has_value() && 
"functor has missing return type");
 
  798                 returnType = udf->getFinalReturnType().value();
 
  800                 assert(
false && 
"unexpected functor type");
 
  804                     mk<ast::BinaryConstraint>(opEq, 
souffle::clone(func), mk<ast::SubroutineArgument>(
i));
 
  805             constraint->setFinalType(opEq);
 
  806             intermediateClause->addToBody(std::move(constraint));
 
  807         } 
else if (
auto rec = 
dynamic_cast<ast::RecordInit*
>(arg)) {
 
  808             auto constraint = mk<ast::BinaryConstraint>(
 
  811             intermediateClause->addToBody(std::move(constraint));
 
  816     size_t levelIndex = head->getArguments().size() - auxiliaryArity;
 
  819     const auto& bodyLiterals = intermediateClause->getBodyLiterals();
 
  820     for (
auto lit : bodyLiterals) {
 
  821         if (
auto atom = 
dynamic_cast<ast::Atom*
>(lit)) {
 
  822             auto arity = atom->getArity();
 
  823             auto atomArgs = atom->getArguments();
 
  826                     souffle::clone(atomArgs[arity - 1]), mk<ast::SubroutineArgument>(levelIndex));
 
  828             intermediateClause->addToBody(std::move(constraint));
 
  831     return ProvenanceClauseTranslator(*this).translateClause(*intermediateClause, clause);
 
  847     auto clauseReplacedAggregates = mk<ast::Clause>(
souffle::clone(clause.getHead()));
 
  850     for (
auto bodyLit : clause.getBodyLiterals()) {
 
  852         if (!isA<ast::Constraint>(bodyLit)) {
 
  858     for (
auto bodyLit : ast::getBodyLiterals<ast::Constraint>(clause)) {
 
  863     struct AggregatesToVariables : 
public ast::NodeMapper {
 
  866         AggregatesToVariables(
int& aggNumber) : aggNumber(aggNumber) {}
 
  868         Own<ast::Node> operator()(Own<ast::Node> node)
 const override {
 
  869             if (
dynamic_cast<ast::Aggregator*
>(node.get()) != 
nullptr) {
 
  870                 return mk<ast::Variable>(
"agg_" + std::to_string(aggNumber++));
 
  878     AggregatesToVariables aggToVar(aggNumber);
 
  879     clauseReplacedAggregates->apply(aggToVar);
 
  882     std::vector<const ast::Variable*> uniqueVariables;
 
  884     visitDepthFirst(*clauseReplacedAggregates, [&](
const ast::Variable& var) {
 
  885         if (var.getName().find(
"@level_num") == std::string::npos) {
 
  888             if (std::find_if(uniqueVariables.begin(), uniqueVariables.end(),
 
  889                         [&](const ast::Variable* v) { return *v == var; }) == uniqueVariables.end()) {
 
  890                 uniqueVariables.push_back(&var);
 
  896     struct VariablesToArguments : 
public ast::NodeMapper {
 
  897         const std::vector<const ast::Variable*>& uniqueVariables;
 
  899         VariablesToArguments(
const std::vector<const ast::Variable*>& uniqueVariables)
 
  900                 : uniqueVariables(uniqueVariables) {}
 
  902         Own<ast::Node> operator()(Own<ast::Node> node)
 const override {
 
  904             if (
auto varPtr = 
dynamic_cast<const ast::Variable*
>(node.get())) {
 
  905                 if (varPtr->getName().find(
"@level_num") == std::string::npos) {
 
  906                     size_t argNum = std::find_if(uniqueVariables.begin(), uniqueVariables.end(),
 
  907                                             [&](
const ast::Variable* v) { return *v == *varPtr; }) -
 
  908                                     uniqueVariables.begin();
 
  910                     return mk<ast::SubroutineArgument>(argNum);
 
  912                     return mk<ast::UnnamedVariable>();
 
  926     VecOwn<ram::Statement> searchSequence;
 
  932     size_t litNumber = 0;
 
  933     for (
const auto& lit : newClause->getBodyLiterals()) {
 
  934         if (
auto atom = 
dynamic_cast<ast::Atom*
>(lit)) {
 
  935             size_t auxiliaryArity = auxArityAnalysis->getArity(atom);
 
  937             auto relName = translateRelation(atom);
 
  939             VecOwn<ram::Expression> query;
 
  942             VariablesToArguments varsToArgs(uniqueVariables);
 
  943             atom->apply(varsToArgs);
 
  945             auto atomArgs = atom->getArguments();
 
  947             for (
size_t i = 0; 
i < atom->getArity() - auxiliaryArity; 
i++) {
 
  948                 auto arg = atomArgs[
i];
 
  949                 query.push_back(translateValue(arg, ValueIndex()));
 
  953             for (
size_t i = 0; 
i < auxiliaryArity; 
i++) {
 
  954                 query.push_back(mk<ram::UndefValue>());
 
  958             assert(query.size() == atom->getArity() && 
"wrong query tuple size");
 
  961             auto existenceCheck = mk<ram::ExistenceCheck>(relName, std::move(query));
 
  962             auto negativeExistenceCheck = mk<ram::Negation>(
souffle::clone(existenceCheck));
 
  965             VecOwn<ram::Expression> returnTrue;
 
  966             returnTrue.push_back(mk<ram::SignedConstant>(1));
 
  969             VecOwn<ram::Expression> returnFalse;
 
  970             returnFalse.push_back(mk<ram::SignedConstant>(0));
 
  973             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(existenceCheck),
 
  974                                                mk<ram::SubroutineReturn>(std::move(returnTrue)))));
 
  975             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(negativeExistenceCheck),
 
  976                                                mk<ram::SubroutineReturn>(std::move(returnFalse)))));
 
  977         } 
else if (
auto neg = 
dynamic_cast<ast::Negation*
>(lit)) {
 
  978             auto atom = neg->getAtom();
 
  980             size_t auxiliaryArity = auxArityAnalysis->getArity(atom);
 
  981             auto relName = translateRelation(atom);
 
  983             VecOwn<ram::Expression> query;
 
  986             VariablesToArguments varsToArgs(uniqueVariables);
 
  987             atom->apply(varsToArgs);
 
  989             auto atomArgs = atom->getArguments();
 
  991             for (
size_t i = 0; 
i < atom->getArity() - auxiliaryArity; 
i++) {
 
  992                 auto arg = atomArgs[
i];
 
  993                 query.push_back(translateValue(arg, ValueIndex()));
 
  997             for (
size_t i = 0; 
i < auxiliaryArity; 
i++) {
 
  998                 query.push_back(mk<ram::UndefValue>());
 
 1002             assert(query.size() == atom->getArity() && 
"wrong query tuple size");
 
 1005             auto existenceCheck = mk<ram::ExistenceCheck>(relName, std::move(query));
 
 1006             auto negativeExistenceCheck = mk<ram::Negation>(
souffle::clone(existenceCheck));
 
 1009             VecOwn<ram::Expression> returnTrue;
 
 1010             returnTrue.push_back(mk<ram::SignedConstant>(1));
 
 1013             VecOwn<ram::Expression> returnFalse;
 
 1014             returnFalse.push_back(mk<ram::SignedConstant>(0));
 
 1017             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(existenceCheck),
 
 1018                                                mk<ram::SubroutineReturn>(std::move(returnFalse)))));
 
 1019             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(negativeExistenceCheck),
 
 1020                                                mk<ram::SubroutineReturn>(std::move(returnTrue)))));
 
 1022         } 
else if (
auto con = 
dynamic_cast<ast::Constraint*
>(lit)) {
 
 1023             VariablesToArguments varsToArgs(uniqueVariables);
 
 1024             con->apply(varsToArgs);
 
 1027             auto condition = translateConstraint(con, ValueIndex());
 
 1028             auto negativeCondition = mk<ram::Negation>(
souffle::clone(condition));
 
 1031             VecOwn<ram::Expression> returnTrue;
 
 1032             returnTrue.push_back(mk<ram::SignedConstant>(1));
 
 1035             VecOwn<ram::Expression> returnFalse;
 
 1036             returnFalse.push_back(mk<ram::SignedConstant>(0));
 
 1038             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(condition),
 
 1039                                                mk<ram::SubroutineReturn>(std::move(returnTrue)))));
 
 1040             appendStmt(searchSequence, mk<ram::Query>(mk<ram::Filter>(std::move(negativeCondition),
 
 1041                                                mk<ram::SubroutineReturn>(std::move(returnFalse)))));
 
 1047     return mk<ram::Sequence>(std::move(searchSequence));
 
 1050 bool AstToRamTranslator::removeADTs(
const ast::TranslationUnit& translationUnit) {
 
 1051     struct ADTsFuneral : 
public ast::NodeMapper {
 
 1052         mutable bool changed{
false};
 
 1053         const ast::analysis::SumTypeBranchesAnalysis& sumTypesBranches;
 
 1055         ADTsFuneral(
const ast::TranslationUnit& tu)
 
 1056                 : sumTypesBranches(*tu.getAnalysis<ast::analysis::SumTypeBranchesAnalysis>()) {}
 
 1062             if (!isA<ast::BranchInit>(node)) {
 
 1067             auto& adt = *as<ast::BranchInit>(node);
 
 1068             auto& 
type = sumTypesBranches.unsafeGetType(adt.getConstructor());
 
 1069             auto& branches = 
type.getBranches();
 
 1073             auto iterToBranch = std::lower_bound(branches.begin(), branches.end(), searchDummy,
 
 1074                     [](
const ast::analysis::AlgebraicDataType::Branch& left,
 
 1075                             const ast::analysis::AlgebraicDataType::Branch& right) {
 
 1076                         return left.name < right.name;
 
 1080             auto branchID = std::distance(std::begin(branches), iterToBranch);
 
 1083                 auto branchTag = mk<ast::NumericConstant>(branchID);
 
 1088                 VecOwn<ast::Argument> branchArguments;
 
 1089                 for (
auto* arg : adt.getArguments()) {
 
 1090                     branchArguments.emplace_back(arg->
clone());
 
 1095                 auto branchArgs = [&]() -> Own<ast::Argument> {
 
 1096                     if (branchArguments.size() != 1) {
 
 1097                         return mk<ast::Argument, ast::RecordInit>(std::move(branchArguments));
 
 1099                         return std::move(branchArguments.at(0));
 
 1104                 VecOwn<ast::Argument> finalRecordArgs;
 
 1106                 auto branchTag = mk<ast::NumericConstant>(branchID);
 
 1108                 finalRecordArgs.push_back(std::move(branchTag));
 
 1109                 finalRecordArgs.push_back(std::move(branchArgs));
 
 1111                 return mk<ast::RecordInit>(std::move(finalRecordArgs), adt.getSrcLoc());
 
 1116     ADTsFuneral mapper(translationUnit);
 
 1117     translationUnit.getProgram().apply(mapper);
 
 1118     return mapper.changed;
 
 1122 void AstToRamTranslator::translateProgram(
const ast::TranslationUnit& translationUnit) {
 
 1124     ioType = translationUnit.getAnalysis<ast::analysis::IOTypeAnalysis>();
 
 1125     typeEnv = &translationUnit.getAnalysis<ast::analysis::TypeEnvironmentAnalysis>()->getTypeEnvironment();
 
 1126     const auto* recursiveClauses = translationUnit.getAnalysis<ast::analysis::RecursiveClausesAnalysis>();
 
 1127     const auto& sccGraph = *translationUnit.getAnalysis<ast::analysis::SCCGraphAnalysis>();
 
 1129     const auto& expirySchedule =
 
 1141         const_cast<ast::Aggregator&
>(aggr).setFinalType(polyAnalysis->getOverloadedOperator(&aggr));
 
 1147         const_cast<ast::IntrinsicFunctor&
>(inf).setFinalOpType(polyAnalysis->getOverloadedFunctionOp(&inf));
 
 1148         const_cast<ast::IntrinsicFunctor&
>(inf).setFinalReturnType(functorAnalysis->getReturnType(&inf));
 
 1151         const_cast<ast::UserDefinedFunctor&
>(udf).setFinalReturnType(functorAnalysis->getReturnType(&udf));
 
 1155     std::string sipsChosen = 
"all-bound";
 
 1162     removeADTs(translationUnit);
 
 1165     if (sccGraph.getNumberOfSCCs() == 0) 
return;
 
 1168     const auto& makeRamLoad = [&](VecOwn<ram::Statement>& current, 
const ast::Relation* 
relation) {
 
 1170             Own<ram::Statement> statement = mk<ram::IO>(translateRelation(
relation), 
directives);
 
 1174                 statement = mk<ram::LogRelationTimer>(
 
 1175                         std::move(statement), logTimerStatement, translateRelation(
relation));
 
 1182     const auto& makeRamStore = [&](VecOwn<ram::Statement>& current, 
const ast::Relation* 
relation) {
 
 1184             Own<ram::Statement> statement = mk<ram::IO>(translateRelation(
relation), 
directives);
 
 1188                 statement = mk<ram::LogRelationTimer>(
 
 1189                         std::move(statement), logTimerStatement, translateRelation(
relation));
 
 1196     const auto& makeRamClear = [&](VecOwn<ram::Statement>& current, 
const ast::Relation* 
relation) {
 
 1201     for (
const auto& scc : sccOrder.order()) {
 
 1202         const auto& isRecursive = sccGraph.isRecursive(scc);
 
 1203         const auto& allInterns = sccGraph.getInternalRelations(scc);
 
 1204         for (
const auto& 
rel : allInterns) {
 
 1205             std::string name = 
rel->getQualifiedName().toString();
 
 1206             auto arity = 
rel->getArity();
 
 1207             auto auxiliaryArity = auxArityAnalysis->getArity(
rel);
 
 1208             auto representation = 
rel->getRepresentation();
 
 1209             const auto& attributes = 
rel->getAttributes();
 
 1211             std::vector<std::string> attributeNames;
 
 1212             std::vector<std::string> attributeTypeQualifiers;
 
 1213             for (
size_t i = 0; 
i < 
rel->getArity(); ++
i) {
 
 1214                 attributeNames.push_back(attributes[
i]->getName());
 
 1215                 if (typeEnv != 
nullptr) {
 
 1216                     attributeTypeQualifiers.push_back(
 
 1220             ramRels[name] = mk<ram::Relation>(
 
 1221                     name, arity, auxiliaryArity, attributeNames, attributeTypeQualifiers, representation);
 
 1225                 std::string deltaName = 
"@delta_" + name;
 
 1226                 std::string newName = 
"@new_" + name;
 
 1227                 ramRels[deltaName] = mk<ram::Relation>(deltaName, arity, auxiliaryArity, attributeNames,
 
 1228                         attributeTypeQualifiers, representation);
 
 1229                 ramRels[newName] = mk<ram::Relation>(newName, arity, auxiliaryArity, attributeNames,
 
 1230                         attributeTypeQualifiers, representation);
 
 1236     size_t indexOfScc = 0;
 
 1239     for (
const auto& scc : sccOrder.order()) {
 
 1241         VecOwn<ram::Statement> current;
 
 1244         const auto& isRecursive = sccGraph.isRecursive(scc);
 
 1248         const auto& allInterns = sccGraph.getInternalRelations(scc);
 
 1249         const auto& internIns = sccGraph.getInternalInputRelations(scc);
 
 1250         const auto& internOuts = sccGraph.getInternalOutputRelations(scc);
 
 1253         const auto& internExps = expirySchedule.at(indexOfScc).expired();
 
 1256         for (
const auto& 
relation : internIns) {
 
 1261         Own<ram::Statement> bodyStatement =
 
 1262                 (!isRecursive) ? translateNonRecursiveRelation(
 
 1263                                          *((
const ast::Relation*)*allInterns.begin()), recursiveClauses)
 
 1264                                : translateRecursiveRelation(allInterns, recursiveClauses);
 
 1265         appendStmt(current, std::move(bodyStatement));
 
 1268         for (
const auto& 
relation : internOuts) {
 
 1274             for (
const auto& 
relation : internExps) {
 
 1280         ramSubs[
"stratum_" + std::to_string(indexOfScc)] = mk<ram::Sequence>(std::move(current));
 
 1285     VecOwn<ram::Statement> res;
 
 1286     for (
size_t i = 0; 
i < indexOfScc; 
i++) {
 
 1287         appendStmt(res, mk<ram::Call>(
"stratum_" + std::to_string(
i)));
 
 1298     ramMain = mk<ram::Sequence>(std::move(res));
 
 1303             std::stringstream relName;
 
 1304             relName << clause.getHead()->getQualifiedName();
 
 1307             if (relName.str().find(
"@info") != std::string::npos || clause.getBodyLiterals().empty()) {
 
 1311             std::string subroutineLabel =
 
 1312                     relName.str() + 
"_" + std::to_string(
getClauseNum(program, &clause)) + 
"_subproof";
 
 1313             ramSubs[subroutineLabel] = makeSubproofSubroutine(clause);
 
 1315             std::string negationSubroutineLabel = relName.str() + 
"_" +
 
 1317                                                   "_negation_subproof";
 
 1318             ramSubs[negationSubroutineLabel] = makeNegationSubproofSubroutine(clause);
 
 1323 Own<ram::TranslationUnit> AstToRamTranslator::translateUnit(ast::TranslationUnit& tu) {
 
 1325     program = &tu.getProgram();
 
 1327     translateProgram(tu);
 
 1328     SymbolTable& symTab = getSymbolTable();
 
 1332     for (
auto& cur : ramRels) {
 
 1333         rels.push_back(std::move(cur.second));
 
 1335     if (ramMain == 
nullptr) {
 
 1336         ramMain = mk<ram::Sequence>();
 
 1338     auto ramProg = mk<ram::Program>(std::move(rels), std::move(ramMain), std::move(ramSubs));
 
 1342             std::string runtimeStr =
 
 1343                     "(" + std::to_string(std::chrono::duration<double>(ram_end - ram_start).
count()) + 
"s)";
 
 1344             std::stringstream ramProgStr;
 
 1345             ramProgStr << *ramProg;
 
 1346             debugReport.
addSection(
"ram-program", 
"RAM Program " + runtimeStr, ramProgStr.str());
 
 1349     return mk<ram::TranslationUnit>(std::move(ramProg), std::move(symTab), errReport, debugReport);