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);