souffle
2.0.2-371-g6315b36
|
Main class for the AST->RAM translator.
More...
#include <AstToRamTranslator.h>
Main class for the AST->RAM translator.
Definition at line 71 of file AstToRamTranslator.h.
◆ AstToRamTranslator()
souffle::ast2ram::AstToRamTranslator::AstToRamTranslator |
( |
| ) |
|
|
default |
◆ ~AstToRamTranslator()
souffle::ast2ram::AstToRamTranslator::~AstToRamTranslator |
( |
| ) |
|
|
default |
◆ getAuxArityAnalysis()
◆ getConstantRamRepresentation()
RamDomain souffle::ast2ram::AstToRamTranslator::getConstantRamRepresentation |
( |
const ast::Constant & |
constant | ) |
|
|
private |
Get ram representation of constant.
Definition at line 418 of file AstToRamTranslator.cpp.
428 fatal(
"unaccounted-for constant");
434 if (
auto*
const c_num =
dynamic_cast<const ast::NumericConstant*
>(&c)) {
435 switch (c_num->getFinalType().value()) {
◆ getEvaluationArity()
size_t souffle::ast2ram::AstToRamTranslator::getEvaluationArity |
( |
const ast::Atom * |
atom | ) |
const |
determine the auxiliary for relations
Definition at line 154 of file AstToRamTranslator.cpp.
165 const ast::Relation*
rel) {
166 std::vector<std::map<std::string, std::string>> inputDirectives;
◆ getFunctorAnalysis()
◆ getInputDirectives()
std::vector< std::map< std::string, std::string > > souffle::ast2ram::AstToRamTranslator::getInputDirectives |
( |
const ast::Relation * |
rel | ) |
|
|
private |
Definition at line 170 of file AstToRamTranslator.cpp.
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;
◆ getOutputDirectives()
std::vector< std::map< std::string, std::string > > souffle::ast2ram::AstToRamTranslator::getOutputDirectives |
( |
const ast::Relation * |
rel | ) |
|
|
private |
Definition at line 194 of file AstToRamTranslator.cpp.
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;
◆ getPolymorphicObjectsAnalysis()
◆ getRelationName()
std::string souffle::ast2ram::AstToRamTranslator::getRelationName |
( |
const ast::QualifiedName & |
id | ) |
|
|
staticprivate |
converts the given relation identifier into a relation name
Definition at line 549 of file AstToRamTranslator.cpp.
551 VecOwn<ram::Statement> preamble;
◆ getSipsMetric()
const ast::SipsMetric* souffle::ast2ram::AstToRamTranslator::getSipsMetric |
( |
| ) |
const |
|
inline |
◆ getSymbolTable()
SymbolTable & souffle::ast2ram::AstToRamTranslator::getSymbolTable |
( |
| ) |
|
|
private |
Return a symbol table.
Definition at line 335 of file AstToRamTranslator.cpp.
336 class ConstraintTranslator :
public ast::Visitor<Own<ram::Condition>> {
338 const ValueIndex& index;
References polyAnalysis.
◆ lookupRelation()
const ram::Relation* souffle::ast2ram::AstToRamTranslator::lookupRelation |
( |
const std::string & |
name | ) |
const |
|
inline |
◆ makeNegationSubproofSubroutine()
translate RAM code for subroutine to get subproofs for non-existence of a tuple
make a subroutine to search for subproofs for the non-existence of a tuple
Definition at line 841 of file AstToRamTranslator.cpp.
850 : 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)) {
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];
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();
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];
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);
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));
1051 struct ADTsFuneral :
public ast::NodeMapper {
1052 mutable bool changed{
false};
1053 const ast::analysis::SumTypeBranchesAnalysis& sumTypesBranches;
◆ makeRamTupleElement()
◆ makeSubproofSubroutine()
translate RAM code for subroutine to get subproofs
make a subroutine to search for subproofs
Definition at line 765 of file AstToRamTranslator.cpp.
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);
References souffle::clone().
◆ nameUnnamedVariables()
void souffle::ast2ram::AstToRamTranslator::nameUnnamedVariables |
( |
ast::Clause * |
clause | ) |
|
|
private |
assigns names to unnamed variables such that enclosing constructs may be cloned without losing the variable-identity
A utility function assigning names to unnamed variables such that enclosing constructs may be cloned without losing the variable-identity.
Definition at line 519 of file AstToRamTranslator.cpp.
525 if (
dynamic_cast<ast::UnnamedVariable*
>(node.get()) !=
nullptr) {
526 auto name =
" _unnamed_var" +
toString(++counter);
527 return mk<ast::Variable>(name);
537 for (
auto& atom : ast::getBodyLiterals<ast::Atom>(*clause)) {
References souffle::toString().
◆ removeADTs()
bool souffle::ast2ram::AstToRamTranslator::removeADTs |
( |
const ast::TranslationUnit & |
translationUnit | ) |
|
|
staticprivate |
replace ADTs with special records
Definition at line 1056 of file AstToRamTranslator.cpp.
1056 : sumTypesBranches(*tu.getAnalysis<ast::analysis::SumTypeBranchesAnalysis>()) {}
1058 Own<ast::Node> operator()(Own<ast::Node> node)
const override {
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();
1072 ast::analysis::AlgebraicDataType::Branch searchDummy{adt.getConstructor(), {}};
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;
1124 ioType = translationUnit.getAnalysis<ast::analysis::IOTypeAnalysis>();
1125 typeEnv = &translationUnit.getAnalysis<ast::analysis::TypeEnvironmentAnalysis>()->getTypeEnvironment();
◆ translateConstant()
translate RAM code for a constant value
Definition at line 437 of file AstToRamTranslator.cpp.
437 :
return mk<ram::UnsignedConstant>(rawConstant);
442 return mk<ram::SignedConstant>(rawConstant);
447 const ast::Relation&
rel,
const ast::analysis::RecursiveClausesAnalysis* recursiveClauses) {
449 VecOwn<ram::Statement> res;
◆ translateConstraint()
translate an AST constraint to a RAM condition
for atoms
for binary relations
for provenance negation
for negations
Definition at line 340 of file AstToRamTranslator.cpp.
343 const ast::analysis::PolymorphicObjectsAnalysis*
polyAnalysis)
347 Own<ram::Condition> visitAtom(
const ast::Atom&)
override {
352 Own<ram::Condition> visitBinaryConstraint(
const ast::BinaryConstraint& binRel)
override {
353 assert(binRel.getFinalType().has_value() &&
"binary constraint has unset type");
354 auto valLHS = translator.translateValue(binRel.getLHS(), index);
355 auto valRHS = translator.translateValue(binRel.getRHS(), index);
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();
362 size_t auxiliaryArity = translator.getEvaluationArity(atom);
363 assert(auxiliaryArity <= atom->getArity() &&
"auxiliary arity out of bounds");
364 size_t arity = atom->getArity() - auxiliaryArity;
365 VecOwn<ram::Expression> values;
367 auto args = atom->getArguments();
368 for (
size_t i = 0;
i < arity;
i++) {
369 values.push_back(translator.translateValue(args[
i], index));
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();
387 size_t auxiliaryArity = translator.getEvaluationArity(atom);
388 assert(auxiliaryArity <= atom->getArity() &&
"auxiliary arity out of bounds");
389 size_t arity = atom->getArity() - auxiliaryArity;
393 return mk<ram::EmptinessCheck>(translator.translateRelation(atom));
397 VecOwn<ram::Expression> values;
398 auto args = atom->getArguments();
399 for (
size_t i = 0;
i < arity;
i++) {
400 values.push_back(translator.translateValue(args[
i], index));
402 for (
size_t i = 0;
i < auxiliaryArity;
i++) {
403 values.push_back(mk<ram::UndefValue>());
405 return mk<ram::Negation>(
406 mk<ram::ExistenceCheck>(translator.translateRelation(atom), std::move(values)));
409 return ConstraintTranslator(*
this, index,
polyAnalysis)(*lit);
413 if (
auto strConstant =
dynamic_cast<const ast::StringConstant*
>(&constant)) {
415 }
else if (isA<ast::NilConstant>(&constant)) {
◆ translateDeltaRelation()
std::string souffle::ast2ram::AstToRamTranslator::translateDeltaRelation |
( |
const ast::Relation * |
rel | ) |
|
|
private |
translate a temporary delta
relation to a RAM relation for semi-naive evaluation
Definition at line 228 of file AstToRamTranslator.cpp.
◆ translateNewRelation()
std::string souffle::ast2ram::AstToRamTranslator::translateNewRelation |
( |
const ast::Relation * |
rel | ) |
|
|
private |
translate a temporary new
relation to a RAM relation for semi-naive evaluation
Definition at line 232 of file AstToRamTranslator.cpp.
235 :
public ast::Visitor<Own<ram::Expression>> {
◆ translateNonRecursiveRelation()
translate RAM code for the non-recursive clauses of the given relation.
generate RAM code for a non-recursive relation
- Returns
- a corresponding statement or null if there are no non-recursive clauses.
Definition at line 452 of file AstToRamTranslator.cpp.
456 if (recursiveClauses->recursive(clause)) {
461 Own<ram::Statement>
rule = ClauseTranslator(*this).translateClause(*clause, *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());
488 const SrcLocation& srcLocation =
rel.getSrcLoc();
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));
References souffle::ast2ram::appendStmt(), souffle::Global::config(), souffle::LogStatement::nNonrecursiveRule(), rel(), rule, souffle::stringify(), souffle::LogStatement::tNonrecursiveRule(), souffle::toString(), and souffle::ast2ram::ClauseTranslator::translateClause().
◆ translateProgram()
void souffle::ast2ram::AstToRamTranslator::translateProgram |
( |
const ast::TranslationUnit & |
translationUnit | ) |
|
|
private |
translate AST to RAM Program
translates the given datalog program into an equivalent RAM program
Definition at line 1128 of file AstToRamTranslator.cpp.
1155 std::string sipsChosen =
"all-bound";
1165 if (sccGraph.getNumberOfSCCs() == 0)
return;
1168 const auto& makeRamLoad = [&](VecOwn<ram::Statement>& current,
const ast::Relation*
relation) {
1174 statement = mk<ram::LogRelationTimer>(
1182 const auto& makeRamStore = [&](VecOwn<ram::Statement>& current,
const ast::Relation*
relation) {
1188 statement = mk<ram::LogRelationTimer>(
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();
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());
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 =
1263 *((
const ast::Relation*)*allInterns.begin()), 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 =
1315 std::string negationSubroutineLabel = relName.str() +
"_" +
1317 "_negation_subproof";
◆ translateRecursiveRelation()
translate RAM code for recursive relations in a strongly-connected component
generate RAM code for recursive relations in a strongly-connected component
Definition at line 554 of file AstToRamTranslator.cpp.
557 VecOwn<ram::Expression> values;
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));
576 for (
const ast::Relation*
rel : scc) {
578 Own<ram::Statement> updateRelTable =
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;
619 if (!recursiveClauses->recursive(cl)) {
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()));
References souffle::EQREL, i, and rel().
◆ translateRelation() [1/2]
std::string souffle::ast2ram::AstToRamTranslator::translateRelation |
( |
const ast::Atom * |
atom | ) |
|
◆ translateRelation() [2/2]
std::string souffle::ast2ram::AstToRamTranslator::translateRelation |
( |
const ast::Relation * |
rel, |
|
|
const std::string |
relationNamePrefix = "" |
|
) |
| |
◆ translateUnit()
translates AST to translation unit
Definition at line 1329 of file AstToRamTranslator.cpp.
1333 rels.push_back(std::move(cur.second));
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);
◆ translateValue()
translate an AST argument to a RAM value
Definition at line 236 of file AstToRamTranslator.cpp.
242 const ast::analysis::PolymorphicObjectsAnalysis*
polyAnalysis)
245 Own<ram::Expression> visitVariable(
const ast::Variable& var)
override {
246 if (!index.isDefined(var))
fatal(
"variable `%s` is not grounded", var);
250 Own<ram::Expression> visitUnnamedVariable(
const ast::UnnamedVariable&)
override {
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 {
269 return mk<ram::SignedConstant>(translator.getSymbolTable().lookup(c.getConstant()));
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 {
277 return translator.translateValue(typeCast.getValue(), index);
280 Own<ram::Expression> visitIntrinsicFunctor(
const ast::IntrinsicFunctor& inf)
override {
281 VecOwn<ram::Expression> values;
282 for (
const auto& cur : inf.getArguments()) {
283 values.push_back(translator.translateValue(cur, index));
287 return translator.makeRamTupleElement(index.getGeneratorLoc(inf));
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()) {
296 values.push_back(translator.translateValue(cur, index));
298 auto returnType = translator.functorAnalysis->getReturnType(&udf);
299 auto argTypes = translator.functorAnalysis->getArgTypes(udf);
300 return mk<ram::UserDefinedOperator>(udf.getName(), argTypes, returnType,
301 translator.functorAnalysis->isStateful(&udf), std::move(values));
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()) {
311 values.push_back(translator.translateValue(cur, index));
313 return mk<ram::PackRecord>(std::move(values));
316 Own<ram::Expression> visitAggregator(
const ast::Aggregator& agg)
override {
318 return translator.makeRamTupleElement(index.getGeneratorLoc(agg));
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;
Referenced by souffle::ast2ram::ProvenanceClauseTranslator::createOperation(), and souffle::ast2ram::ClauseTranslator::translateClause().
◆ auxArityAnalysis
◆ functorAnalysis
◆ ioType
◆ polyAnalysis
◆ program
const ast::Program* souffle::ast2ram::AstToRamTranslator::program = nullptr |
|
private |
◆ ramMain
◆ ramRels
std::map<std::string, Own<ram::Relation> > souffle::ast2ram::AstToRamTranslator::ramRels |
|
private |
◆ ramSubs
std::map<std::string, Own<ram::Statement> > souffle::ast2ram::AstToRamTranslator::ramSubs |
|
private |
◆ sips
◆ typeEnv
The documentation for this class was generated from the following files:
Own< ast::SipsMetric > sips
SIPS metric for reordering.
static const std::string nNonrecursiveRule(const std::string &relationName, const SrcLocation &srcLocation, const std::string &datalogText)
RamSigned RamSignedFromString(const std::string &str, std::size_t *position=nullptr, const int base=10)
Converts a string to a RamSigned.
static bool isMultiResult(const Functor &functor)
RamDomain getConstantRamRepresentation(const ast::Constant &constant)
Get ram representation of constant.
Own< ram::Statement > ramMain
RAM program.
Own< ram::Statement > translateNonRecursiveRelation(const ast::Relation &rel, const ast::analysis::RecursiveClausesAnalysis *recursiveClauses)
translate RAM code for the non-recursive clauses of the given relation.
NumericConstant::Type getInferredType(const NumericConstant *nc) const
static const std::string cRecursiveRelation(const std::string &relationName, const SrcLocation &srcLocation)
const ast::analysis::AuxiliaryArityAnalysis * auxArityAnalysis
Auxiliary Arity Analysis.
bool isADTEnum(const AlgebraicDataType &type)
Determine if ADT is enumerations (are all constructors empty)
std::map< std::string, Own< ram::Statement > > ramSubs
Subroutines.
const Type & getType(const QualifiedName &) const
static const std::string tRecursiveRelation(const std::string &relationName, const SrcLocation &srcLocation)
void nameUnnamedVariables(ast::Clause *clause)
assigns names to unnamed variables such that enclosing constructs may be cloned without losing the va...
size_t getClauseNum(const Program *program, const Clause *clause)
Returns the index of a clause within its relation, ignoring facts.
static const std::string runtime()
const ast::analysis::FunctorAnalysis * functorAnalysis
Functors' analysis.
std::string translateDeltaRelation(const ast::Relation *rel)
translate a temporary delta relation to a RAM relation for semi-naive evaluation
std::vector< std::map< std::string, std::string > > getInputDirectives(const ast::Relation *rel)
FunctorOp getOverloadedFunctionOp(const IntrinsicFunctor *inf) const
const ast::Program * program
AST program.
std::map< std::string, Own< ram::Relation > > ramRels
RAM relations.
std::string translateRelation(const ast::Atom *atom)
a utility to translate atoms to relations
std::string unescape(const std::string &inputString, const std::string &needle, const std::string &replacement)
bool isLimitSize(const Relation *relation) const
static std::unique_ptr< SipsMetric > create(const std::string &heuristic, const TranslationUnit &tu)
Create a SIPS metric based on a given heuristic.
static const std::string nRecursiveRule(const std::string &relationName, const int version, const SrcLocation &srcLocation, const std::string &datalogText)
const std::string & toString(const std::string &str)
A generic function converting strings into strings (trivial case).
RamDomain lookup(const std::string &symbol)
Find the index of a symbol in the table, inserting a new symbol if it does not exist there already.
static const std::string nRecursiveRelation(const std::string &relationName, const SrcLocation &srcLocation)
std::string stringify(const std::string &input)
Stringify a string using escapes for escape, newline, tab, double-quotes and semicolons.
auto clone(const std::vector< A * > &xs)
detail::joined_sequence< Iter, Printer > join(const Iter &a, const Iter &b, const std::string &sep, const Printer &p)
Creates an object to be forwarded to some output stream for printing sequences of elements interspers...
Own< ram::Condition > translateConstraint(const ast::Literal *arg, const ValueIndex &index)
translate an AST constraint to a RAM condition
static const std::string tNonrecursiveRelation(const std::string &relationName, const SrcLocation &srcLocation)
static const std::string tNonrecursiveRule(const std::string &relationName, const SrcLocation &srcLocation, const std::string &datalogText)
const ast::analysis::PolymorphicObjectsAnalysis * polyAnalysis
Polymorphic Objects Analysis.
TypeAttribute getReturnType(const Functor *functor) const
Return return type of functor.
Own< ram::Statement > makeNegationSubproofSubroutine(const ast::Clause &clause)
translate RAM code for subroutine to get subproofs for non-existence of a tuple
constexpr auto get(span< E, S > s) -> decltype(s[N])
static const std::string tRelationLoadTime(const std::string &relationName, const SrcLocation &srcLocation)
const ast::analysis::TypeEnvironment * typeEnv
Type environment.
std::vector< Clause * > getClauses(const Program &program, const QualifiedName &relationName)
Returns a vector of clauses in the program describing the relation with the given name.
std::vector< Directive * > getDirectives() const
Return relation directives.
void translateProgram(const ast::TranslationUnit &translationUnit)
translate AST to RAM Program
static bool removeADTs(const ast::TranslationUnit &translationUnit)
replace ADTs with special records
static std::string getRelationName(const ast::QualifiedName &id)
converts the given relation identifier into a relation name
std::string translateNewRelation(const ast::Relation *rel)
translate a temporary new relation to a RAM relation for semi-naive evaluation
std::vector< Own< Directive > > directives
void appendStmt(VecOwn< ram::Statement > &stmtList, Own< ram::Statement > stmt)
append statement to a list of statements
std::size_t getLimitSize(const Relation *relation) const
static MainConfig & config()
static Own< ram::TupleElement > makeRamTupleElement(const Location &loc)
create a RAM element access node
Own< ram::Statement > makeSubproofSubroutine(const ast::Clause &clause)
translate RAM code for subroutine to get subproofs
SymbolTable & getSymbolTable()
Return a symbol table.
static const std::string nNonrecursiveRelation(const std::string &relationName, const SrcLocation &srcLocation)
static const std::string tRecursiveRule(const std::string &relationName, const int version, const SrcLocation &srcLocation, const std::string &datalogText)
void fatal(const char *format, const Args &... args)
Own< ram::Expression > translateValue(const ast::Argument *arg, const ValueIndex &index)
translate an AST argument to a RAM value
size_t getArity(const Atom *atom) const
Returns the number of auxiliary parameters of an atom's relation.
const ast::analysis::IOTypeAnalysis * ioType
IO Type.
RamUnsigned RamUnsignedFromString(const std::string &str, std::size_t *position=nullptr, const int base=10)
Converts a string to a RamUnsigned.
const Relation * getAtomRelation(const Atom *atom, const Program *program)
Returns the relation referenced by the given atom.
Own< ram::TranslationUnit > translateUnit(ast::TranslationUnit &tu)
translates AST to translation unit
void visitDepthFirst(const Node &root, Visitor< R, Ps... > &visitor, Args &... args)
A utility function visiting all nodes within the ast rooted by the given node recursively in a depth-...
Own< ram::Expression > translateConstant(ast::Constant const &c)
translate RAM code for a constant value
static const std::string tRelationSaveTime(const std::string &relationName, const SrcLocation &srcLocation)
std::string getTypeQualifier(const Type &type)
Returns full type qualifier for a given type.
RamFloat RamFloatFromString(const std::string &str, std::size_t *position=nullptr)
Converts a string to a RamFloat.
void rel(size_t limit, bool showLimit=true)
BinaryConstraintOp getOverloadedOperator(const BinaryConstraint *bc) const
std::vector< std::map< std::string, std::string > > getOutputDirectives(const ast::Relation *rel)
Own< ram::Statement > translateRecursiveRelation(const std::set< const ast::Relation * > &scc, const ast::analysis::RecursiveClausesAnalysis *recursiveClauses)
translate RAM code for recursive relations in a strongly-connected component