kythe.io@v0.0.68-0.20240422202219-7225dbc01741/third_party/souffle/parse_transform.cc (about)

     1  /*
     2   * Souffle - A Datalog Compiler
     3   * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
     4   * Licensed under the Universal Permissive License v 1.0 as shown at:
     5   * - https://opensource.org/licenses/UPL
     6   * - <souffle root>/licenses/SOUFFLE-UPL.txt
     7   */
     8  
     9  // This code was originally in <souffle root>/src/main.cpp.
    10  
    11  #include "absl/log/log.h"
    12  #include "third_party/souffle/parse_transform.h"
    13  
    14  #include "Global.h"
    15  #include "ast/Clause.h"
    16  #include "ast/Node.h"
    17  #include "ast/Program.h"
    18  #include "ast/TranslationUnit.h"
    19  #include "ast/analysis/PrecedenceGraph.h"
    20  #include "ast/analysis/SCCGraph.h"
    21  #include "ast/analysis/typesystem/Type.h"
    22  #include "ast/transform/AddNullariesToAtomlessAggregates.h"
    23  #include "ast/transform/ComponentChecker.h"
    24  #include "ast/transform/ComponentInstantiation.h"
    25  #include "ast/transform/Conditional.h"
    26  #include "ast/transform/ExecutionPlanChecker.h"
    27  #include "ast/transform/ExpandEqrels.h"
    28  #include "ast/transform/Fixpoint.h"
    29  #include "ast/transform/FoldAnonymousRecords.h"
    30  #include "ast/transform/GroundWitnesses.h"
    31  #include "ast/transform/GroundedTermsChecker.h"
    32  #include "ast/transform/IOAttributes.h"
    33  #include "ast/transform/IODefaults.h"
    34  #include "ast/transform/InlineRelations.h"
    35  #include "ast/transform/MagicSet.h"
    36  #include "ast/transform/MaterializeAggregationQueries.h"
    37  #include "ast/transform/MaterializeSingletonAggregation.h"
    38  #include "ast/transform/MinimiseProgram.h"
    39  #include "ast/transform/NameUnnamedVariables.h"
    40  #include "ast/transform/NormaliseGenerators.h"
    41  #include "ast/transform/PartitionBodyLiterals.h"
    42  #include "ast/transform/Pipeline.h"
    43  #include "ast/transform/PragmaChecker.h"
    44  #include "ast/transform/ReduceExistentials.h"
    45  #include "ast/transform/RemoveBooleanConstraints.h"
    46  #include "ast/transform/RemoveEmptyRelations.h"
    47  #include "ast/transform/RemoveRedundantRelations.h"
    48  #include "ast/transform/RemoveRedundantSums.h"
    49  #include "ast/transform/RemoveRelationCopies.h"
    50  #include "ast/transform/ReplaceSingletonVariables.h"
    51  #include "ast/transform/ResolveAliases.h"
    52  #include "ast/transform/ResolveAnonymousRecordAliases.h"
    53  #include "ast/transform/SemanticChecker.h"
    54  #include "ast/transform/SimplifyAggregateTargetExpression.h"
    55  #include "ast/transform/SubsumptionQualifier.h"
    56  #include "ast/transform/UniqueAggregationVariables.h"
    57  #include "ast2ram/TranslationStrategy.h"
    58  #include "ast2ram/UnitTranslator.h"
    59  #include "ast2ram/provenance/TranslationStrategy.h"
    60  #include "ast2ram/provenance/UnitTranslator.h"
    61  #include "ast2ram/seminaive/TranslationStrategy.h"
    62  #include "ast2ram/seminaive/UnitTranslator.h"
    63  #include "ast2ram/utility/TranslatorContext.h"
    64  #include "interpreter/Engine.h"
    65  #include "interpreter/ProgInterface.h"
    66  #include "parser/ParserDriver.h"
    67  #include "ram/Node.h"
    68  #include "ram/Program.h"
    69  #include "ram/TranslationUnit.h"
    70  #include "ram/transform/CollapseFilters.h"
    71  #include "ram/transform/Conditional.h"
    72  #include "ram/transform/EliminateDuplicates.h"
    73  #include "ram/transform/ExpandFilter.h"
    74  #include "ram/transform/HoistAggregate.h"
    75  #include "ram/transform/HoistConditions.h"
    76  #include "ram/transform/IfConversion.h"
    77  #include "ram/transform/IfExistsConversion.h"
    78  #include "ram/transform/Loop.h"
    79  #include "ram/transform/MakeIndex.h"
    80  #include "ram/transform/Parallel.h"
    81  #include "ram/transform/ReorderConditions.h"
    82  #include "ram/transform/ReorderFilterBreak.h"
    83  #include "ram/transform/ReportIndex.h"
    84  #include "ram/transform/Sequence.h"
    85  #include "ram/transform/Transformer.h"
    86  #include "ram/transform/TupleId.h"
    87  #include "reports/DebugReport.h"
    88  #include "reports/ErrorReport.h"
    89  #include "souffle/RamTypes.h"
    90  #include "souffle/utility/ContainerUtil.h"
    91  #include "souffle/utility/FileUtil.h"
    92  #include "souffle/utility/MiscUtil.h"
    93  #include "souffle/utility/StreamUtil.h"
    94  #include "souffle/utility/StringUtil.h"
    95  #include "souffle/utility/SubProcess.h"
    96  #include "synthesiser/Synthesiser.h"
    97  #include <cassert>
    98  #include <chrono>
    99  #include <cstdio>
   100  #include <cstdlib>
   101  #include <ctime>
   102  #include <iomanip>
   103  #include <iostream>
   104  #include <map>
   105  #include <memory>
   106  #include <set>
   107  #include <sstream>
   108  #include <stdexcept>
   109  #include <string>
   110  #include <thread>
   111  #include <utility>
   112  #include <vector>
   113  
   114  namespace souffle {
   115  
   116  std::unique_ptr<ram::TranslationUnit> ParseTransform(const std::string& code) {
   117    Global::config().set("jobs", "1");
   118    Global::config().has("verbose", "1");
   119    souffle::ErrorReport errorReport(/*nowarn=*/true);
   120    souffle::DebugReport debugReport;
   121    souffle::Own<souffle::ast::TranslationUnit> astTranslationUnit =
   122        souffle::ParserDriver::parseTranslationUnit(code, errorReport, debugReport);
   123    auto& report = astTranslationUnit->getErrorReport();
   124    if (report.getNumIssues() != 0) {
   125        LOG(ERROR) << "Souffle parser reported a nonzero diagnostic count.";
   126        std::stringstream diagnostics;
   127        diagnostics << report;
   128        LOG(ERROR) << diagnostics.str();
   129        return nullptr;
   130    }
   131  
   132    // ------- rewriting / optimizations -------------
   133  
   134    /* set up additional global options based on pragma declaratives */
   135    (mk<ast::transform::PragmaChecker>())->apply(*astTranslationUnit);
   136  
   137    /* construct the transformation pipeline */
   138  
   139    // Equivalence pipeline
   140    auto equivalencePipeline =
   141            mk<ast::transform::PipelineTransformer>(mk<ast::transform::NameUnnamedVariablesTransformer>(),
   142                    mk<ast::transform::FixpointTransformer>(mk<ast::transform::MinimiseProgramTransformer>()),
   143                    mk<ast::transform::ReplaceSingletonVariablesTransformer>(),
   144                    mk<ast::transform::RemoveRelationCopiesTransformer>(),
   145                    mk<ast::transform::RemoveEmptyRelationsTransformer>(),
   146                    mk<ast::transform::RemoveRedundantRelationsTransformer>());
   147  
   148    // Magic-Set pipeline
   149    auto magicPipeline = mk<ast::transform::PipelineTransformer>(
   150            mk<ast::transform::ConditionalTransformer>(
   151                    Global::config().has("magic-transform"), mk<ast::transform::ExpandEqrelsTransformer>()),
   152            mk<ast::transform::MagicSetTransformer>(), mk<ast::transform::ResolveAliasesTransformer>(),
   153            mk<ast::transform::RemoveRelationCopiesTransformer>(),
   154            mk<ast::transform::RemoveEmptyRelationsTransformer>(),
   155            mk<ast::transform::RemoveRedundantRelationsTransformer>(), clone(equivalencePipeline));
   156  
   157    // Partitioning pipeline
   158    auto partitionPipeline =
   159            mk<ast::transform::PipelineTransformer>(mk<ast::transform::NameUnnamedVariablesTransformer>(),
   160                    mk<ast::transform::PartitionBodyLiteralsTransformer>(),
   161                    mk<ast::transform::ReplaceSingletonVariablesTransformer>());
   162  
   163    // Provenance pipeline
   164    auto provenancePipeline = mk<ast::transform::ConditionalTransformer>(Global::config().has("provenance"),
   165            mk<ast::transform::PipelineTransformer>(mk<ast::transform::ExpandEqrelsTransformer>(),
   166                    mk<ast::transform::NameUnnamedVariablesTransformer>()));
   167  
   168    // Main pipeline
   169    auto pipeline = mk<ast::transform::PipelineTransformer>(mk<ast::transform::ComponentChecker>(),
   170            mk<ast::transform::ComponentInstantiationTransformer>(),
   171            mk<ast::transform::IODefaultsTransformer>(),
   172            mk<ast::transform::SimplifyAggregateTargetExpressionTransformer>(),
   173            mk<ast::transform::UniqueAggregationVariablesTransformer>(),
   174            mk<ast::transform::FixpointTransformer>(mk<ast::transform::PipelineTransformer>(
   175                    mk<ast::transform::ResolveAnonymousRecordAliasesTransformer>(),
   176                    mk<ast::transform::FoldAnonymousRecords>())),
   177            mk<ast::transform::SubsumptionQualifierTransformer>(), mk<ast::transform::SemanticChecker>(),
   178            mk<ast::transform::GroundWitnessesTransformer>(),
   179            mk<ast::transform::UniqueAggregationVariablesTransformer>(),
   180            mk<ast::transform::MaterializeSingletonAggregationTransformer>(),
   181            mk<ast::transform::FixpointTransformer>(
   182                    mk<ast::transform::MaterializeAggregationQueriesTransformer>()),
   183            mk<ast::transform::RemoveRedundantSumsTransformer>(),
   184            mk<ast::transform::NormaliseGeneratorsTransformer>(),
   185            mk<ast::transform::ResolveAliasesTransformer>(),
   186            mk<ast::transform::RemoveBooleanConstraintsTransformer>(),
   187            mk<ast::transform::ResolveAliasesTransformer>(), mk<ast::transform::MinimiseProgramTransformer>(),
   188            mk<ast::transform::InlineUnmarkExcludedTransform>(),
   189            mk<ast::transform::InlineRelationsTransformer>(), mk<ast::transform::GroundedTermsChecker>(),
   190            mk<ast::transform::ResolveAliasesTransformer>(),
   191            mk<ast::transform::RemoveRedundantRelationsTransformer>(),
   192            mk<ast::transform::RemoveRelationCopiesTransformer>(),
   193            mk<ast::transform::RemoveEmptyRelationsTransformer>(),
   194            mk<ast::transform::ReplaceSingletonVariablesTransformer>(),
   195            mk<ast::transform::FixpointTransformer>(mk<ast::transform::PipelineTransformer>(
   196                    mk<ast::transform::ReduceExistentialsTransformer>(),
   197                    mk<ast::transform::RemoveRedundantRelationsTransformer>())),
   198            mk<ast::transform::RemoveRelationCopiesTransformer>(), std::move(partitionPipeline),
   199            std::move(equivalencePipeline), mk<ast::transform::RemoveRelationCopiesTransformer>(),
   200            std::move(magicPipeline), mk<ast::transform::RemoveEmptyRelationsTransformer>(),
   201            mk<ast::transform::AddNullariesToAtomlessAggregatesTransformer>(),
   202            mk<ast::transform::ExecutionPlanChecker>(), std::move(provenancePipeline),
   203            mk<ast::transform::IOAttributesTransformer>());
   204  
   205    // Disable unwanted transformations
   206    if (Global::config().has("disable-transformers")) {
   207        std::vector<std::string> givenTransformers =
   208                splitString(Global::config().get("disable-transformers"), ',');
   209        pipeline->disableTransformers(
   210                std::set<std::string>(givenTransformers.begin(), givenTransformers.end()));
   211    }
   212  
   213    // Toggle pipeline verbosity
   214    pipeline->setVerbosity(Global::config().has("verbose"));
   215  
   216    // Apply all the transformations
   217    pipeline->apply(*astTranslationUnit);
   218  
   219    // ------- execution -------------
   220    /* translate AST to RAM */
   221    debugReport.startSection();
   222    auto translationStrategy =
   223            Global::config().has("provenance")
   224                    ? mk<ast2ram::TranslationStrategy, ast2ram::provenance::TranslationStrategy>()
   225                    : mk<ast2ram::TranslationStrategy, ast2ram::seminaive::TranslationStrategy>();
   226    auto unitTranslator = Own<ast2ram::UnitTranslator>(translationStrategy->createUnitTranslator());
   227    auto ramTranslationUnit = unitTranslator->translateUnit(*astTranslationUnit);
   228    debugReport.endSection("ast-to-ram", "Translate AST to RAM");
   229  
   230    // Apply RAM transforms
   231    {
   232        using namespace ram::transform;
   233        Own<Transformer> ramTransform = mk<TransformerSequence>(
   234                mk<LoopTransformer>(mk<TransformerSequence>(mk<ExpandFilterTransformer>(),
   235                        mk<HoistConditionsTransformer>(), mk<MakeIndexTransformer>())),
   236                mk<IfConversionTransformer>(), mk<IfExistsConversionTransformer>(),
   237                mk<CollapseFiltersTransformer>(), mk<TupleIdTransformer>(),
   238                mk<LoopTransformer>(
   239                        mk<TransformerSequence>(mk<HoistAggregateTransformer>(), mk<TupleIdTransformer>())),
   240                mk<ExpandFilterTransformer>(), mk<HoistConditionsTransformer>(),
   241                mk<CollapseFiltersTransformer>(), mk<EliminateDuplicatesTransformer>(),
   242                mk<ReorderConditionsTransformer>(), mk<LoopTransformer>(mk<ReorderFilterBreak>()),
   243                mk<ConditionalTransformer>(
   244                        // job count of 0 means all cores are used.
   245                        []() -> bool { return std::stoi(Global::config().get("jobs")) != 1; },
   246                        mk<ParallelTransformer>()),
   247                mk<ReportIndexTransformer>());
   248  
   249        ramTransform->apply(*ramTranslationUnit);
   250    }
   251  
   252    if (ramTranslationUnit->getErrorReport().getNumIssues() != 0) {
   253        std::cerr << ramTranslationUnit->getErrorReport();
   254    }
   255  
   256    return ramTranslationUnit;
   257  }
   258  
   259  }