From 04ff3b7004bd9923cc4a09c05e0aef9ed692c37e Mon Sep 17 00:00:00 2001 From: Quentin Sabah Date: Fri, 18 Nov 2022 05:23:15 +0100 Subject: [PATCH] remove `Global` singleton --- cmake/common.py | 1 + cmake/redirect.py | 5 + src/Global.cpp | 6 +- src/Global.h | 11 +- src/TranslationUnitBase.h | 12 +- src/ast/Program.h | 1 + src/ast/TranslationUnit.cpp | 3 +- src/ast/TranslationUnit.h | 3 +- src/ast/analysis/JoinSize.cpp | 8 +- src/ast/analysis/JoinSize.h | 2 +- src/ast/analysis/ProfileUse.cpp | 7 +- src/ast/analysis/SCCGraph.cpp | 3 +- src/ast/analysis/SCCGraph.h | 2 + src/ast/analysis/typesystem/Type.cpp | 3 +- src/ast/tests/ast_print_test.cpp | 10 +- src/ast/tests/ast_program_test.cpp | 33 +-- src/ast/tests/ast_transformers_test.cpp | 50 ++-- src/ast/tests/ast_utils_test.cpp | 20 +- src/ast/transform/IODefaults.h | 11 +- src/ast/transform/InlineRelations.cpp | 6 +- src/ast/transform/InlineRelations.h | 2 +- src/ast/transform/MagicSet.cpp | 6 +- src/ast/transform/PragmaChecker.cpp | 11 +- src/ast/transform/PragmaChecker.h | 5 +- src/ast/transform/SemanticChecker.cpp | 4 +- src/ast/transform/TypeChecker.cpp | 2 +- src/ast2ram/provenance/ClauseTranslator.cpp | 2 +- src/ast2ram/provenance/UnitTranslator.cpp | 4 +- src/ast2ram/provenance/UnitTranslator.h | 2 + src/ast2ram/seminaive/ClauseTranslator.cpp | 4 +- src/ast2ram/seminaive/UnitTranslator.cpp | 29 ++- src/ast2ram/seminaive/UnitTranslator.h | 6 + src/ast2ram/utility/SipsMetric.cpp | 2 +- src/ast2ram/utility/TranslatorContext.cpp | 7 +- src/ast2ram/utility/TranslatorContext.h | 9 + src/interpreter/Engine.cpp | 41 ++-- src/interpreter/Engine.h | 26 ++- src/interpreter/Generator.cpp | 44 ++-- src/interpreter/Generator.h | 2 + src/interpreter/Node.h | 4 +- .../tests/interpreter_relation_test.cpp | 2 +- src/interpreter/tests/ram_arithmetic_test.cpp | 9 +- src/interpreter/tests/ram_relation_test.cpp | 63 ++--- src/main.cpp | 215 +++++++++--------- src/parser/ParserDriver.cpp | 22 +- src/parser/ParserDriver.h | 10 +- src/ram/TranslationUnit.cpp | 3 +- src/ram/transform/MakeIndex.cpp | 9 +- src/ram/transform/MakeIndex.h | 6 +- src/ram/transform/Transformer.cpp | 4 +- src/reports/DebugReport.cpp | 31 ++- src/reports/DebugReport.h | 22 +- src/synthesiser/Synthesiser.cpp | 67 +++--- src/synthesiser/Synthesiser.h | 6 +- 54 files changed, 511 insertions(+), 367 deletions(-) diff --git a/cmake/common.py b/cmake/common.py index 9e999d04c68..28fe8f1d844 100644 --- a/cmake/common.py +++ b/cmake/common.py @@ -45,6 +45,7 @@ def compare_files(expected_file, actual_file): if actual_lines != expected_lines: os.sys.stdout.writelines(difflib.unified_diff(open(expected_file).readlines(), open(actual_file).readlines(), fromfile=expected_file, tofile=actual_file)) + os.sys.stdout.write("\n") os.sys.exit("Found output difference, expected file:'{}', actual file:'{}".format(expected_file, actual_file)) return True diff --git a/cmake/redirect.py b/cmake/redirect.py index d1b703e61a3..7f833ddabf0 100644 --- a/cmake/redirect.py +++ b/cmake/redirect.py @@ -41,4 +41,9 @@ if stderr: stderr.close() +if status.returncode != 0 and args.err_file: + with open(args.err_file, "r") as f: + os.sys.stderr.write(f.read()) + + os.sys.exit(status.returncode) diff --git a/src/Global.cpp b/src/Global.cpp index f8436900dd8..68f673a0b14 100644 --- a/src/Global.cpp +++ b/src/Global.cpp @@ -182,7 +182,7 @@ void MainConfig::processArgs(int argc, char** argv, const std::string& header, c while ((c = getopt_long(argc, argv, shortNames.c_str(), longNames.get(), nullptr)) != -1) { // case for the unknown option if (c == '?') { - std::cerr << Global::config().help(); + std::cerr << help(); throw std::runtime_error("Error: Unknown command line option."); } // obtain an iterator to the option in the table referenced by the current short name @@ -217,11 +217,11 @@ void MainConfig::processArgs(int argc, char** argv, const std::string& header, c } // obtain the name of the datalog file, and store it in the option with the empty key - if (argc > 1 && !Global::config().has("help") && !Global::config().has("version")) { + if (argc > 1 && !has("help") && !has("version")) { std::string filename = ""; // ensure that the optind is less than the total number of arguments if (argc > 1 && optind >= argc) { - std::cerr << Global::config().help(); + std::cerr << help(); throw std::runtime_error("Error: Missing source file path."); } diff --git a/src/Global.h b/src/Global.h index 866fd6123ed..5e633349c0e 100644 --- a/src/Global.h +++ b/src/Global.h @@ -104,18 +104,21 @@ class MainConfig { * used to isolate all globals. */ class Global { public: + Global() = default; /* Deleted copy constructor. */ Global(const Global&) = delete; /* Deleted assignment operator. */ Global& operator=(const Global&) = delete; /* Obtain the global configuration. */ - static MainConfig& config() { - static MainConfig _config; + MainConfig& config() { + return _config; + } + + const MainConfig& config() const { return _config; } private: - /* Private empty constructor, there is only one global instance. */ - Global() = default; + MainConfig _config; }; } // namespace souffle diff --git a/src/TranslationUnitBase.h b/src/TranslationUnitBase.h index e97ebecd2b5..42f80de5e2c 100644 --- a/src/TranslationUnitBase.h +++ b/src/TranslationUnitBase.h @@ -16,6 +16,7 @@ #pragma once +#include "Global.h" #include "reports/DebugReport.h" #include "reports/ErrorReport.h" #include "souffle/utility/DynamicCasting.h" @@ -72,8 +73,8 @@ struct TranslationUnitBase { virtual void run(Impl const&) = 0; }; - TranslationUnitBase(Own prog, ErrorReport& e, DebugReport& d) - : program(std::move(prog)), errorReport(e), debugReport(d) { + TranslationUnitBase(Global& g, Own prog, ErrorReport& e, DebugReport& d) + : glb(g), program(std::move(prog)), errorReport(e), debugReport(d) { assert(program != nullptr && "program is a null-pointer"); } @@ -109,6 +110,11 @@ struct TranslationUnitBase { analyses.clear(); } + /** @brief Get the global configuration */ + Global& global() const { + return glb; + } + /** @brief Get the RAM Program of the translation unit */ Program& getProgram() const { return *program; @@ -133,6 +139,8 @@ struct TranslationUnitBase { // Using `std::string` appears to suppress the issue (bug?). mutable std::map> analyses; + Global& glb; + /* RAM program */ Own program; diff --git a/src/ast/Program.h b/src/ast/Program.h index 1316f0dcd32..c3475ef458d 100644 --- a/src/ast/Program.h +++ b/src/ast/Program.h @@ -16,6 +16,7 @@ #pragma once +#include "Global.h" #include "ast/Clause.h" #include "ast/Component.h" #include "ast/ComponentInit.h" diff --git a/src/ast/TranslationUnit.cpp b/src/ast/TranslationUnit.cpp index a2975b64272..c1be8f6aa7e 100644 --- a/src/ast/TranslationUnit.cpp +++ b/src/ast/TranslationUnit.cpp @@ -8,6 +8,7 @@ #include "ast/TranslationUnit.h" #include "Global.h" +#include "ast/Program.h" #include "ast/analysis/PrecedenceGraph.h" #include "ast/analysis/SCCGraph.h" #include "reports/DebugReport.h" @@ -17,7 +18,7 @@ namespace souffle::ast { /** get analysis: analysis is generated on the fly if not present */ void TranslationUnit::logAnalysis(Analysis& analysis) const { - if (!Global::config().has("debug-report")) return; + if (!global().config().has("debug-report")) return; std::string name = analysis.getName(); if (as(analysis) || as(analysis)) { diff --git a/src/ast/TranslationUnit.h b/src/ast/TranslationUnit.h index d3aeea7f8de..21e21caac1c 100644 --- a/src/ast/TranslationUnit.h +++ b/src/ast/TranslationUnit.h @@ -16,12 +16,11 @@ #pragma once +#include "Program.h" #include "TranslationUnitBase.h" namespace souffle::ast { -class Program; - /** * @class TranslationUnit * @brief Translation unit class for the translation pipeline diff --git a/src/ast/analysis/JoinSize.cpp b/src/ast/analysis/JoinSize.cpp index d550ffbbef8..10659a0153e 100644 --- a/src/ast/analysis/JoinSize.cpp +++ b/src/ast/analysis/JoinSize.cpp @@ -120,7 +120,8 @@ analysis::StratumJoinSizeEstimates JoinSizeAnalysis::computeRuleVersionStatement return statements; } -std::vector JoinSizeAnalysis::computeJoinSizeStatements() { +std::vector JoinSizeAnalysis::computeJoinSizeStatements( + const bool emitStatistics) { auto* prog = program; auto getSccAtoms = [prog](const ast::Clause* clause, const ast::RelationSet& scc) { const auto& sccAtoms = filter(ast::getBodyLiterals(*clause), @@ -133,8 +134,7 @@ std::vector JoinSizeAnalysis::computeJoinSiz std::vector joinSizeStatements; joinSizeStatements.resize(sccOrdering.size()); - auto& config = Global::config(); - if (!config.has("emit-statistics")) { + if (!emitStatistics) { return joinSizeStatements; } @@ -240,7 +240,7 @@ void JoinSizeAnalysis::run(const TranslationUnit& translationUnit) { topsortSCCGraphAnalysis = &translationUnit.getAnalysis(); recursiveClauses = &translationUnit.getAnalysis(); polyAnalysis = &translationUnit.getAnalysis(); - joinSizeStatements = computeJoinSizeStatements(); + joinSizeStatements = computeJoinSizeStatements(translationUnit.global().config().has("emit-statistics")); } void JoinSizeAnalysis::print(std::ostream& os) const { diff --git a/src/ast/analysis/JoinSize.h b/src/ast/analysis/JoinSize.h index cd071baa3cc..3d3b79a312c 100644 --- a/src/ast/analysis/JoinSize.h +++ b/src/ast/analysis/JoinSize.h @@ -68,7 +68,7 @@ class JoinSizeAnalysis : public Analysis { PolymorphicObjectsAnalysis* polyAnalysis = nullptr; // for each stratum compute the EstimateJoinSize nodes to emit - std::vector computeJoinSizeStatements(); + std::vector computeJoinSizeStatements(bool emitStatistics); StratumJoinSizeEstimates computeRuleVersionStatements(const RelationSet& sccRelations, const ast::Clause& clause, std::size_t version, ast2ram::TranslationMode mode = ast2ram::TranslationMode::DEFAULT); diff --git a/src/ast/analysis/ProfileUse.cpp b/src/ast/analysis/ProfileUse.cpp index 3ee50ff7212..b6fc8ce7ee7 100644 --- a/src/ast/analysis/ProfileUse.cpp +++ b/src/ast/analysis/ProfileUse.cpp @@ -17,6 +17,7 @@ #include "ast/analysis/ProfileUse.h" #include "Global.h" +#include "ast/Program.h" #include "ast/QualifiedName.h" #include "souffle/profile/ProgramRun.h" #include "souffle/profile/Reader.h" @@ -29,10 +30,10 @@ namespace souffle::ast::analysis { /** * Run analysis, i.e., retrieve profile information */ -void ProfileUseAnalysis::run(const TranslationUnit&) { +void ProfileUseAnalysis::run(const TranslationUnit& TU) { std::string filename; - if (Global::config().has("auto-schedule")) { - filename = Global::config().get("auto-schedule"); + if (TU.global().config().has("auto-schedule")) { + filename = TU.global().config().get("auto-schedule"); } reader = mk(filename, programRun); reader->processFile(); diff --git a/src/ast/analysis/SCCGraph.cpp b/src/ast/analysis/SCCGraph.cpp index b9cbd9c29b2..b05a2b6cebb 100644 --- a/src/ast/analysis/SCCGraph.cpp +++ b/src/ast/analysis/SCCGraph.cpp @@ -36,6 +36,7 @@ namespace souffle::ast::analysis { void SCCGraphAnalysis::run(const TranslationUnit& translationUnit) { precedenceGraph = &translationUnit.getAnalysis(); ioType = &translationUnit.getAnalysis(); + programName = translationUnit.global().config().get("name"); sccToRelation.clear(); relationToScc.clear(); predecessors.clear(); @@ -115,7 +116,7 @@ void SCCGraphAnalysis::scR(const Relation* w, std::map makeATU(std::string program = ".decl A,B,C(x:number)") { + Global glb; ErrorReport e; - DebugReport d; - return ParserDriver::parseTranslationUnit(program, e, d); + DebugReport d(glb); + return ParserDriver::parseTranslationUnit(glb, program, e, d); } inline Own makePrintedATU(Own& tu) { @@ -84,11 +85,12 @@ TEST(AstPrint, NumberConstant) { } TEST(AstPrint, StringConstant) { + Global glb; ErrorReport e; - DebugReport d; + DebugReport d(glb); auto testArgument = mk("test string"); - auto tu1 = ParserDriver::parseTranslationUnit(".decl A,B,C(x:number)", e, d); + auto tu1 = ParserDriver::parseTranslationUnit(glb, ".decl A,B,C(x:number)", e, d); tu1->getProgram().addClause(makeClauseA(std::move(testArgument))); auto tu2 = makePrintedATU(tu1); EXPECT_EQ(tu1->getProgram(), tu2->getProgram()); diff --git a/src/ast/tests/ast_program_test.cpp b/src/ast/tests/ast_program_test.cpp index 8980765edbc..9dd55cb9c1a 100644 --- a/src/ast/tests/ast_program_test.cpp +++ b/src/ast/tests/ast_program_test.cpp @@ -43,9 +43,10 @@ namespace souffle::ast::test { inline Own makeATU(std::string program) { + Global glb; ErrorReport e; - DebugReport d; - return ParserDriver::parseTranslationUnit(program, e, d); + DebugReport d(glb); + return ParserDriver::parseTranslationUnit(glb, program, e, d); } inline Own makeClause(std::string name, Own headArgument) { @@ -56,16 +57,17 @@ inline Own makeClause(std::string name, Own headArgument) { } TEST(Program, Parse) { + Global glb; ErrorReport e; - DebugReport d; + DebugReport d(glb); // check the empty program - Own empty = ParserDriver::parseTranslationUnit("", e, d); + Own empty = ParserDriver::parseTranslationUnit(glb, "", e, d); EXPECT_TRUE(empty->getProgram().getTypes().empty()); EXPECT_TRUE(empty->getProgram().getRelations().empty()); // check something simple - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type Node <: symbol .decl e ( a : Node , b : Node ) @@ -87,16 +89,17 @@ TEST(Program, Parse) { EXPECT_FALSE(prog.getRelation("n")); } -#define TESTASTCLONEANDEQUAL(SUBTYPE, DL) \ - TEST(Ast, CloneAndEqual##SUBTYPE) { \ - ErrorReport e; \ - DebugReport d; \ - Own tu = ParserDriver::parseTranslationUnit(DL, e, d); \ - Program& program = tu->getProgram(); \ - EXPECT_EQ(program, program); \ - Own cl(clone(program)); \ - EXPECT_NE(cl.get(), &program); \ - EXPECT_EQ(*cl, program); \ +#define TESTASTCLONEANDEQUAL(SUBTYPE, DL) \ + TEST(Ast, CloneAndEqual##SUBTYPE) { \ + Global glb; \ + ErrorReport e; \ + DebugReport d(glb); \ + Own tu = ParserDriver::parseTranslationUnit(glb, DL, e, d); \ + Program& program = tu->getProgram(); \ + EXPECT_EQ(program, program); \ + Own cl(clone(program)); \ + EXPECT_NE(cl.get(), &program); \ + EXPECT_EQ(*cl, program); \ } TESTASTCLONEANDEQUAL(Program, diff --git a/src/ast/tests/ast_transformers_test.cpp b/src/ast/tests/ast_transformers_test.cpp index 274e02a80de..c06d22e57f2 100644 --- a/src/ast/tests/ast_transformers_test.cpp +++ b/src/ast/tests/ast_transformers_test.cpp @@ -44,10 +44,11 @@ namespace souffle::ast::transform::test { using namespace analysis; TEST(Transformers, GroundTermPropagation) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); // load some test program - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D <: symbol .decl p(a:D,b:D) @@ -75,10 +76,11 @@ TEST(Transformers, GroundTermPropagation) { } TEST(Transformers, GroundTermPropagation2) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); // load some test program - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D <: symbol .decl p(a:D,b:D) @@ -103,9 +105,10 @@ TEST(Transformers, GroundTermPropagation2) { TEST(Transformers, ResolveGroundedAliases) { // load some test program + Global glb; ErrorReport errorReport; - DebugReport debugReport; - Own tu = ParserDriver::parseTranslationUnit( + DebugReport debugReport(glb); + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D <: symbol .decl p(a:D,b:D) @@ -126,9 +129,10 @@ TEST(Transformers, ResolveGroundedAliases) { TEST(Transformers, ResolveAliasesWithTermsInAtoms) { // load some test program + Global glb; ErrorReport errorReport; - DebugReport debugReport; - Own tu = ParserDriver::parseTranslationUnit( + DebugReport debugReport(glb); + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D <: symbol .decl p(a:D,b:D) @@ -163,10 +167,11 @@ TEST(Transformers, ResolveAliasesWithTermsInAtoms) { */ TEST(Transformers, RemoveRelationCopies) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); // load some test program - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D = number .decl a(a:D,b:D) @@ -208,10 +213,11 @@ TEST(Transformers, RemoveRelationCopies) { * */ TEST(Transformers, RemoveRelationCopiesOutput) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); // load some test program - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type D = number .decl a(a:D,b:D) @@ -242,10 +248,11 @@ TEST(Transformers, RemoveRelationCopiesOutput) { * Test the equivalence (or lack of equivalence) of clauses using the MinimiseProgramTransfomer. */ TEST(Transformers, CheckClausalEquivalence) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .decl A(x:number, y:number) .decl B(x:number) @@ -333,10 +340,11 @@ TEST(Transformers, CheckClausalEquivalence) { * Test the equivalence (or lack of equivalence) of aggregators using the MinimiseProgramTransfomer. */ TEST(Transformers, CheckAggregatorEquivalence) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .decl A,B,C,D(X:number) input // first and second are equivalent @@ -396,10 +404,11 @@ TEST(Transformers, CheckAggregatorEquivalence) { * e.g. a(x) :- a(x), x != 0. is only true if a(x) is already true */ TEST(Transformers, RemoveClauseRedundancies) { + Global glb; ErrorReport errorReport; - DebugReport debugReport; + DebugReport debugReport(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .decl a,b,c(X:number) a(0). @@ -453,10 +462,11 @@ TEST(Transformers, RemoveClauseRedundancies) { * (4) MagicSetTransformer */ TEST(Transformers, MagicSetComprehensive) { + Global glb; ErrorReport e; - DebugReport d; + DebugReport d(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( // Stratum 0 - Base Relations .decl BaseOne(X:number) magic diff --git a/src/ast/tests/ast_utils_test.cpp b/src/ast/tests/ast_utils_test.cpp index 6839e6b18df..317b6633448 100644 --- a/src/ast/tests/ast_utils_test.cpp +++ b/src/ast/tests/ast_utils_test.cpp @@ -78,11 +78,12 @@ TEST(AstUtils, Grounded) { // check construction EXPECT_EQ("r(X,Y,Z) :- \n a(X),\n X = Y,\n !b(Z).", toString(*clause)); + Global glb; auto program = mk(); program->addClause(std::move(clause)); - DebugReport dbgReport; + DebugReport dbgReport(glb); ErrorReport errReport; - TranslationUnit tu{std::move(program), errReport, dbgReport}; + TranslationUnit tu{glb, std::move(program), errReport, dbgReport}; // obtain groundness auto isGrounded = analysis::getGroundedTerms(tu, *tu.getProgram().getClauses()[0]); @@ -95,9 +96,10 @@ TEST(AstUtils, Grounded) { } TEST(AstUtils, GroundedRecords) { + Global glb; ErrorReport e; - DebugReport d; - Own tu = ParserDriver::parseTranslationUnit( + DebugReport d(glb); + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .type N <: symbol .type R = [ a : N, B : N ] @@ -132,10 +134,11 @@ TEST(AstUtils, GroundedRecords) { } TEST(AstUtils, ReorderClauseAtoms) { + Global glb; ErrorReport e; - DebugReport d; + DebugReport d(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .decl a,b,c,d,e(x:number) a(x) :- b(x), c(x), 1 != 2, d(y), !e(z), c(z), e(x). @@ -168,10 +171,11 @@ TEST(AstUtils, ReorderClauseAtoms) { } TEST(AstUtils, RemoveEquivalentClauses) { + Global glb; ErrorReport e; - DebugReport d; + DebugReport d(glb); - Own tu = ParserDriver::parseTranslationUnit( + Own tu = ParserDriver::parseTranslationUnit(glb, R"( .decl a() a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). a(). diff --git a/src/ast/transform/IODefaults.h b/src/ast/transform/IODefaults.h index 5ce256361df..990553e9f89 100644 --- a/src/ast/transform/IODefaults.h +++ b/src/ast/transform/IODefaults.h @@ -68,6 +68,7 @@ class IODefaultsTransformer : public Transformer { bool setDefaults(TranslationUnit& translationUnit) { bool changed = false; Program& program = translationUnit.getProgram(); + const Global& glb = translationUnit.global(); for (Directive* io : program.getDirectives()) { // Don't do anything for a directive which // is not an I/O directive @@ -91,19 +92,19 @@ class IODefaultsTransformer : public Transformer { io->addParameter("operation", "input"); changed = true; // Configure input directory - if (Global::config().has("fact-dir")) { - io->addParameter("fact-dir", Global::config().get("fact-dir")); + if (glb.config().has("fact-dir")) { + io->addParameter("fact-dir", glb.config().get("fact-dir")); } } else if (io->getType() == ast::DirectiveType::output) { io->addParameter("operation", "output"); changed = true; // Configure output directory - if (Global::config().has("output-dir")) { - if (Global::config().has("output-dir", "-")) { + if (glb.config().has("output-dir")) { + if (glb.config().has("output-dir", "-")) { io->addParameter("IO", "stdout"); io->addParameter("headers", "true"); } else { - io->addParameter("output-dir", Global::config().get("output-dir")); + io->addParameter("output-dir", glb.config().get("output-dir")); } } } else if (io->getType() == ast::DirectiveType::printsize) { diff --git a/src/ast/transform/InlineRelations.cpp b/src/ast/transform/InlineRelations.cpp index b890758cb04..62b6ea6a618 100644 --- a/src/ast/transform/InlineRelations.cpp +++ b/src/ast/transform/InlineRelations.cpp @@ -1027,10 +1027,10 @@ std::vector getInlinedClause(Program& program, const Clause& clause) { } } -ExcludedRelations InlineRelationsTransformer::excluded() { +ExcludedRelations InlineRelationsTransformer::excluded(Global& glb) { ExcludedRelations xs; auto addAll = [&](const std::string& name) { - for (auto&& r : splitString(Global::config().get(name), ',')) + for (auto&& r : splitString(glb.config().get(name), ',')) xs.insert(QualifiedName(r)); }; @@ -1092,7 +1092,7 @@ bool InlineUnmarkExcludedTransform::transform(TranslationUnit& translationUnit) bool changed = false; Program& program = translationUnit.getProgram(); - auto&& excluded = InlineRelationsTransformer::excluded(); + auto&& excluded = InlineRelationsTransformer::excluded(translationUnit.global()); for (Relation* rel : program.getRelations()) { // no-magic implies no inlining diff --git a/src/ast/transform/InlineRelations.h b/src/ast/transform/InlineRelations.h index 6c7466e5e4d..51c036d1f86 100644 --- a/src/ast/transform/InlineRelations.h +++ b/src/ast/transform/InlineRelations.h @@ -30,7 +30,7 @@ namespace souffle::ast::transform { class InlineRelationsTransformer : public Transformer { public: using ExcludedRelations = std::set; - static ExcludedRelations excluded(); + static ExcludedRelations excluded(Global& glb); std::string getName() const override { return "InlineRelationsTransformer"; diff --git a/src/ast/transform/MagicSet.cpp b/src/ast/transform/MagicSet.cpp index e2439c3c1b9..cff3d3588d1 100644 --- a/src/ast/transform/MagicSet.cpp +++ b/src/ast/transform/MagicSet.cpp @@ -94,14 +94,14 @@ std::set MagicSetTransformer::getWeaklyIgnoredRelations(const Tra std::set weaklyIgnoredRelations; // Add magic-transform-exclude relations to the weakly ignored set - for (const auto& relStr : splitString(Global::config().get("magic-transform-exclude"), ',')) { + for (const auto& relStr : splitString(tu.global().config().get("magic-transform-exclude"), ',')) { std::vector qualifiers = splitString(relStr, '.'); weaklyIgnoredRelations.insert(QualifiedName(qualifiers)); } // Pick up specified relations from config std::set specifiedRelations; - for (const auto& relStr : splitString(Global::config().get("magic-transform"), ',')) { + for (const auto& relStr : splitString(tu.global().config().get("magic-transform"), ',')) { std::vector qualifiers = splitString(relStr, '.'); specifiedRelations.insert(QualifiedName(qualifiers)); } @@ -274,7 +274,7 @@ std::set MagicSetTransformer::getRelationsToNotLabel(const Transl bool MagicSetTransformer::shouldRun(const TranslationUnit& tu) { const Program& program = tu.getProgram(); - if (Global::config().has("magic-transform")) return true; + if (tu.global().config().has("magic-transform")) return true; for (const auto* rel : program.getRelations()) { if (rel->hasQualifier(RelationQualifier::MAGIC)) return true; } diff --git a/src/ast/transform/PragmaChecker.cpp b/src/ast/transform/PragmaChecker.cpp index efd06102728..a4a1776e93a 100644 --- a/src/ast/transform/PragmaChecker.cpp +++ b/src/ast/transform/PragmaChecker.cpp @@ -26,8 +26,8 @@ namespace souffle::ast::transform { -PragmaChecker::Merger::Merger() { - auto& config = Global::config(); +PragmaChecker::Merger::Merger(Global& g) : glb(g) { + auto& config = glb.config(); for (auto&& [k, v] : config.data()) { if (config.state(k) == MainConfig::State::set) { @@ -40,7 +40,7 @@ bool PragmaChecker::Merger::operator()(std::string_view k, std::string_view v) { // Command line options take precedence, even if the param allows multiple if (contains(locked_keys, k)) return false; - auto& config = Global::config(); + auto& config = glb.config(); if (config.allowsMultiple(k)) config.append(k, std::string(v)); else @@ -50,9 +50,10 @@ bool PragmaChecker::Merger::operator()(std::string_view k, std::string_view v) { } bool PragmaChecker::transform(TranslationUnit& translationUnit) { - Merger merger; + Merger merger(translationUnit.global()); auto& program = translationUnit.getProgram(); + auto& glb = translationUnit.global(); auto& error = translationUnit.getErrorReport(); bool changed = false; std::map previous_pragma; @@ -62,7 +63,7 @@ bool PragmaChecker::transform(TranslationUnit& translationUnit) { auto&& [k, v] = pragma->getkvp(); // warn if subsequent pragmas override one another - if (!Global::config().allowsMultiple(k)) { + if (!glb.config().allowsMultiple(k)) { auto it = previous_pragma.find(k); if (it != previous_pragma.end()) { error.addDiagnostic({Diagnostic::Type::WARNING, diff --git a/src/ast/transform/PragmaChecker.h b/src/ast/transform/PragmaChecker.h index 3f6b7751154..d975da146aa 100644 --- a/src/ast/transform/PragmaChecker.h +++ b/src/ast/transform/PragmaChecker.h @@ -32,10 +32,13 @@ class PragmaChecker : public Transformer { // This helper is used to implement both `--pragma` cmd ln args and `.pragma` statements. struct Merger { - Merger(); + Merger(Global&); bool operator()(std::string_view key, std::string_view value); std::set> locked_keys; + + private: + Global& glb; }; private: diff --git a/src/ast/transform/SemanticChecker.cpp b/src/ast/transform/SemanticChecker.cpp index dd63e303353..682545c94d5 100644 --- a/src/ast/transform/SemanticChecker.cpp +++ b/src/ast/transform/SemanticChecker.cpp @@ -138,9 +138,9 @@ bool SemanticChecker::transform(TranslationUnit& translationUnit) { SemanticCheckerImpl::SemanticCheckerImpl(TranslationUnit& tu) : tu(tu) { // suppress warnings for given relations - if (Global::config().has("suppress-warnings")) { + if (tu.global().config().has("suppress-warnings")) { std::vector suppressedRelations = - splitString(Global::config().get("suppress-warnings"), ','); + splitString(tu.global().config().get("suppress-warnings"), ','); if (std::find(suppressedRelations.begin(), suppressedRelations.end(), "*") != suppressedRelations.end()) { diff --git a/src/ast/transform/TypeChecker.cpp b/src/ast/transform/TypeChecker.cpp index 033e19be9f9..c639cd3ce3b 100644 --- a/src/ast/transform/TypeChecker.cpp +++ b/src/ast/transform/TypeChecker.cpp @@ -367,7 +367,7 @@ void TypeCheckerImpl::visit_(type_identity, const Atom& atom) { return isA(type) && !isA(type); }); - if (!validAttribute && !Global::config().has("legacy")) { + if (!validAttribute && !tu.global().config().has("legacy")) { auto primaryDiagnostic = DiagnosticMessage("Atom's argument type is not a subtype of its declared type", arguments[i]->getSrcLoc()); diff --git a/src/ast2ram/provenance/ClauseTranslator.cpp b/src/ast2ram/provenance/ClauseTranslator.cpp index c695fdd60db..0cd0e20bf95 100644 --- a/src/ast2ram/provenance/ClauseTranslator.cpp +++ b/src/ast2ram/provenance/ClauseTranslator.cpp @@ -133,7 +133,7 @@ Own ClauseTranslator::addAtomScan(Own op, const // add a scan level std::stringstream ss; - if (Global::config().has("profile")) { + if (context.getGlobal()->config().has("profile")) { ss << "@frequency-atom" << ';'; ss << clause.getHead()->getQualifiedName() << ';'; ss << version << ';'; diff --git a/src/ast2ram/provenance/UnitTranslator.cpp b/src/ast2ram/provenance/UnitTranslator.cpp index bc8185b5fbe..6c105d882d7 100644 --- a/src/ast2ram/provenance/UnitTranslator.cpp +++ b/src/ast2ram/provenance/UnitTranslator.cpp @@ -50,6 +50,8 @@ namespace souffle::ast2ram::provenance { Own UnitTranslator::generateProgram(const ast::TranslationUnit& translationUnit) { + glb = &translationUnit.global(); + // Do the regular translation auto ramProgram = seminaive::UnitTranslator::generateProgram(translationUnit); @@ -287,7 +289,7 @@ Own UnitTranslator::generateInfoClauses(const ast::Program* progr auto infoClause = mk(std::move(factInsertion)); // Add logging - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { std::stringstream clauseText; clauseText << "@info.clause[" << stringify(toString(*clause)) << "]"; const std::string logTimerStatement = diff --git a/src/ast2ram/provenance/UnitTranslator.h b/src/ast2ram/provenance/UnitTranslator.h index 0ce8f2c41f7..d110fdd5b06 100644 --- a/src/ast2ram/provenance/UnitTranslator.h +++ b/src/ast2ram/provenance/UnitTranslator.h @@ -74,6 +74,8 @@ class UnitTranslator : public ast2ram::seminaive::UnitTranslator { ram::Node* node, const std::map& idToVar) const; Own makeIfStatement( Own condition, Own trueOp, Own falseOp) const; + + Global* glb; }; } // namespace souffle::ast2ram::provenance diff --git a/src/ast2ram/seminaive/ClauseTranslator.cpp b/src/ast2ram/seminaive/ClauseTranslator.cpp index 149fd4ca145..bb69250f1ad 100644 --- a/src/ast2ram/seminaive/ClauseTranslator.cpp +++ b/src/ast2ram/seminaive/ClauseTranslator.cpp @@ -116,7 +116,7 @@ Own ClauseTranslator::translateRecursiveClause( Own rule = translateNonRecursiveClause(clause); // Add logging - if (Global::config().has("profile")) { + if (context.getGlobal()->config().has("profile")) { const std::string& relationName = getConcreteRelationName(clause.getHead()->getQualifiedName()); const auto& srcLocation = clause.getSrcLoc(); const std::string clauseText = stringify(toString(clause)); @@ -238,7 +238,7 @@ Own ClauseTranslator::addAtomScan(Own op, const } std::stringstream ss; - if (Global::config().has("profile")) { + if (context.getGlobal()->config().has("profile")) { ss << "@frequency-atom" << ';'; ss << clause.getHead()->getQualifiedName() << ';'; ss << version << ';'; diff --git a/src/ast2ram/seminaive/UnitTranslator.cpp b/src/ast2ram/seminaive/UnitTranslator.cpp index 8e7d57ad035..96a1169b19a 100644 --- a/src/ast2ram/seminaive/UnitTranslator.cpp +++ b/src/ast2ram/seminaive/UnitTranslator.cpp @@ -112,7 +112,7 @@ Own UnitTranslator::generateNonRecursiveRelation(const ast::Rela Own rule = context->translateNonRecursiveClause(*clause); // Add logging - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { const std::string& relationName = toString(rel.getQualifiedName()); const auto& srcLocation = clause->getSrcLoc(); const std::string clauseText = stringify(toString(*clause)); @@ -132,7 +132,7 @@ Own UnitTranslator::generateNonRecursiveRelation(const ast::Rela } // Add logging for entire relation - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { const std::string& relationName = toString(rel.getQualifiedName()); const auto& srcLocation = rel.getSrcLoc(); const std::string logSizeStatement = LogStatement::nNonrecursiveRelation(relationName, srcLocation); @@ -403,7 +403,7 @@ Own UnitTranslator::generateNonRecursiveDelete(const ast::Relati context->translateNonRecursiveClause(*clause, SubsumeDeleteCurrentCurrent); // Add logging for subsumptive clause - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { const std::string& relationName = toString(rel->getQualifiedName()); const auto& srcLocation = clause->getSrcLoc(); const std::string clauseText = stringify(toString(*clause)); @@ -478,7 +478,7 @@ Own UnitTranslator::generateStratumTableUpdates(const ast::Relat } // Measure update time - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { updateRelTable = mk(std::move(updateRelTable), LogStatement::cRecursiveRelation(toString(rel->getQualifiedName()), rel->getSrcLoc()), newRelation); @@ -492,8 +492,11 @@ Own UnitTranslator::generateStratumTableUpdates(const ast::Relat Own UnitTranslator::generateStratumLoopBody(const ast::RelationSet& scc) const { VecOwn loopBody; - auto addProfiling = [](const ast::Relation* rel, Own stmt) -> Own { - if (Global::config().has("profile")) { + const bool hasProfile = glb->config().has("profile"); + + auto addProfiling = [hasProfile]( + const ast::Relation* rel, Own stmt) -> Own { + if (hasProfile) { const std::string& relationName = toString(rel->getQualifiedName()); const auto& srcLocation = rel->getSrcLoc(); const std::string logTimerStatement = LogStatement::tRecursiveRelation(relationName, srcLocation); @@ -595,7 +598,7 @@ Own UnitTranslator::generateLoadRelation(const ast::Relation* re for (const auto& [key, value] : load->getParameters()) { directives.insert(std::make_pair(key, unescape(value))); } - if (Global::config().has("no-warn")) { + if (glb->config().has("no-warn")) { directives.insert(std::make_pair("no-warn", "true")); } addAuxiliaryArity(relation, directives); @@ -603,7 +606,7 @@ Own UnitTranslator::generateLoadRelation(const ast::Relation* re // Create the resultant load statement, with profile information std::string ramRelationName = getConcreteRelationName(relation->getQualifiedName()); Own loadStmt = mk(ramRelationName, directives); - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { const std::string logTimerStatement = LogStatement::tRelationLoadTime(ramRelationName, relation->getSrcLoc()); loadStmt = mk(std::move(loadStmt), logTimerStatement, ramRelationName); @@ -626,7 +629,7 @@ Own UnitTranslator::generateStoreRelation(const ast::Relation* r // Create the resultant store statement, with profile information std::string ramRelationName = getConcreteRelationName(relation->getQualifiedName()); Own storeStmt = mk(ramRelationName, directives); - if (Global::config().has("profile")) { + if (glb->config().has("profile")) { const std::string logTimerStatement = LogStatement::tRelationSaveTime(ramRelationName, relation->getSrcLoc()); storeStmt = mk(std::move(storeStmt), logTimerStatement, ramRelationName); @@ -723,7 +726,7 @@ Own UnitTranslator::generateProgram(const ast::TranslationUnit& t } // Add main timer if profiling - if (!res.empty() && Global::config().has("profile")) { + if (!res.empty() && glb->config().has("profile")) { auto newStmt = mk(mk(std::move(res)), LogStatement::runtime()); res.clear(); appendStmt(res, std::move(newStmt)); @@ -734,6 +737,8 @@ Own UnitTranslator::generateProgram(const ast::TranslationUnit& t } Own UnitTranslator::translateUnit(ast::TranslationUnit& tu) { + glb = &tu.global(); + /* -- Set-up -- */ auto ram_start = std::chrono::high_resolution_clock::now(); context = mk(tu); @@ -753,7 +758,7 @@ Own UnitTranslator::translateUnit(ast::TranslationUnit& tu mk(std::move(ramRelations), std::move(ramMain), std::move(ramSubroutines)); // Add the translated program to the debug report - if (Global::config().has("debug-report")) { + if (glb->config().has("debug-report")) { auto ram_end = std::chrono::high_resolution_clock::now(); std::string runtimeStr = "(" + std::to_string(std::chrono::duration(ram_end - ram_start).count()) + "s)"; @@ -763,7 +768,7 @@ Own UnitTranslator::translateUnit(ast::TranslationUnit& tu } // Wrap the program into a translation unit - return mk(std::move(ramProgram), errReport, debugReport); + return mk(tu.global(), std::move(ramProgram), errReport, debugReport); } } // namespace souffle::ast2ram::seminaive diff --git a/src/ast2ram/seminaive/UnitTranslator.h b/src/ast2ram/seminaive/UnitTranslator.h index 5b93e0fac36..781e761648b 100644 --- a/src/ast2ram/seminaive/UnitTranslator.h +++ b/src/ast2ram/seminaive/UnitTranslator.h @@ -21,6 +21,10 @@ #include #include +namespace souffle { +class Global; +} + namespace souffle::ast { class Clause; class Relation; @@ -95,6 +99,8 @@ class UnitTranslator : public ast2ram::UnitTranslator { private: std::map> ramSubroutines; + + Global* glb; }; } // namespace souffle::ast2ram::seminaive diff --git a/src/ast2ram/utility/SipsMetric.cpp b/src/ast2ram/utility/SipsMetric.cpp index b579cb8cc9a..1a9d525ed3e 100644 --- a/src/ast2ram/utility/SipsMetric.cpp +++ b/src/ast2ram/utility/SipsMetric.cpp @@ -309,7 +309,7 @@ std::vector SelingerProfileSipsMetric::getReordering( /** Create a SIPS metric based on a given heuristic. */ std::unique_ptr SipsMetric::create(const std::string& heuristic, const TranslationUnit& tu) { - if (Global::config().has("auto-schedule")) { + if (tu.global().config().has("auto-schedule")) { return mk(tu); } else if (heuristic == "strict") return mk(tu); diff --git a/src/ast2ram/utility/TranslatorContext.cpp b/src/ast2ram/utility/TranslatorContext.cpp index 7055fbcab9a..88faf2824ae 100644 --- a/src/ast2ram/utility/TranslatorContext.cpp +++ b/src/ast2ram/utility/TranslatorContext.cpp @@ -50,6 +50,7 @@ namespace souffle::ast2ram { TranslatorContext::TranslatorContext(const ast::TranslationUnit& tu) { program = &tu.getProgram(); + global = &tu.global(); // Set up analyses functorAnalysis = &tu.getAnalysis(); @@ -76,13 +77,13 @@ TranslatorContext::TranslatorContext(const ast::TranslationUnit& tu) { // Set up SIPS metric std::string sipsChosen = "all-bound"; - if (Global::config().has("RamSIPS")) { - sipsChosen = Global::config().get("RamSIPS"); + if (global->config().has("RamSIPS")) { + sipsChosen = global->config().get("RamSIPS"); } sipsMetric = ast::SipsMetric::create(sipsChosen, tu); // Set up the correct strategy - if (Global::config().has("provenance")) { + if (global->config().has("provenance")) { translationStrategy = mk(); } else { translationStrategy = mk(); diff --git a/src/ast2ram/utility/TranslatorContext.h b/src/ast2ram/utility/TranslatorContext.h index 690266d218e..c04f780472d 100644 --- a/src/ast2ram/utility/TranslatorContext.h +++ b/src/ast2ram/utility/TranslatorContext.h @@ -30,6 +30,10 @@ #include #include +namespace souffle { +class Global; +} + namespace souffle::ast { class Aggregator; class Atom; @@ -77,6 +81,10 @@ class TranslatorContext { TranslatorContext(const ast::TranslationUnit& tu); ~TranslatorContext(); + const Global* getGlobal() const { + return global; + } + const ast::Program* getProgram() const { return program; } @@ -146,6 +154,7 @@ class TranslatorContext { private: const ast::Program* program; + const Global* global; const ast::analysis::RecursiveClausesAnalysis* recursiveClauses; const ast::analysis::RelationScheduleAnalysis* relationSchedule; const ast::analysis::SCCGraphAnalysis* sccGraph; diff --git a/src/interpreter/Engine.cpp b/src/interpreter/Engine.cpp index a2092dfdacd..47837d9f289 100644 --- a/src/interpreter/Engine.cpp +++ b/src/interpreter/Engine.cpp @@ -88,6 +88,7 @@ #include "souffle/SignalHandler.h" #include "souffle/SymbolTable.h" #include "souffle/TypeAttribute.h" +#include "souffle/datastructure/RecordTableImpl.h" #include "souffle/datastructure/SymbolTableImpl.h" #include "souffle/io/IOSystem.h" #include "souffle/io/ReadStream.h" @@ -299,10 +300,10 @@ RamDomain callStateless(ExecuteFn&& execute, Context& ctxt, Shadow& shadow, souf } // namespace -Engine::Engine(ram::TranslationUnit& tUnit) - : profileEnabled(Global::config().has("profile")), - frequencyCounterEnabled(Global::config().has("profile-frequency")), - numOfThreads(number_of_threads(std::stoi(Global::config().get("jobs")))), tUnit(tUnit), +Engine::Engine(ram::TranslationUnit& tUnit, const std::size_t numberOfThreadsOrZero) + : tUnit(tUnit), global(tUnit.global()), profileEnabled(global.config().has("profile")), + frequencyCounterEnabled(global.config().has("profile-frequency")), + numOfThreads(number_of_threads(numberOfThreadsOrZero)), isa(tUnit.getAnalysis()), recordTable(numOfThreads), symbolTable(numOfThreads), regexCache(numOfThreads) {} @@ -320,6 +321,14 @@ RamDomain Engine::incCounter() { return counter++; } +Global& Engine::getGlobal() { + return global; +} + +SymbolTable& Engine::getSymbolTable() { + return symbolTable; +} + RecordTable& Engine::getRecordTable() { return recordTable; } @@ -366,19 +375,19 @@ const std::vector& Engine::loadDLL() { return dll; } - if (!Global::config().has("libraries")) { - Global::config().set("libraries", "functors"); + if (!global.config().has("libraries")) { + global.config().set("libraries", "functors"); } - if (!Global::config().has("library-dir")) { - Global::config().set("library-dir", "."); + if (!global.config().has("library-dir")) { + global.config().set("library-dir", "."); } - for (auto&& library : Global::config().getMany("libraries")) { + for (auto&& library : global.config().getMany("libraries")) { // The library may be blank if (library.empty()) { continue; } - auto paths = Global::config().getMany("library-dir"); + auto paths = global.config().getMany("library-dir"); // Set up our paths to have a library appended for (std::string& path : paths) { if (path.back() != pathSeparator) { @@ -422,7 +431,7 @@ void Engine::resetIterationNumber() { void Engine::executeMain() { SignalHandler::instance()->set(); - if (Global::config().has("verbose")) { + if (global.config().has("verbose")) { SignalHandler::instance()->enableLogging(); } @@ -437,7 +446,7 @@ void Engine::executeMain() { Context ctxt; execute(main.get(), ctxt); } else { - ProfileEventSingleton::instance().setOutputFile(Global::config().get("profile")); + ProfileEventSingleton::instance().setOutputFile(global.config().get("profile")); // Prepare the frequency table for threaded use const ram::Program& program = tUnit.getProgram(); visit(program, [&](const ram::TupleOperation& node) { @@ -450,7 +459,7 @@ void Engine::executeMain() { ProfileEventSingleton::instance().startTimer(); ProfileEventSingleton::instance().makeTimeEvent("@time;starttime"); // Store configuration - for (auto&& [k, vs] : Global::config().data()) + for (auto&& [k, vs] : global.config().data()) for (auto&& v : vs) ProfileEventSingleton::instance().makeConfigRecord(k, v); @@ -771,7 +780,7 @@ RamDomain Engine::execute(const Node* node, Context& ctxt) { fatal("ICE: functor `%s` must map onto `NestedIntrinsicOperator`", cur.getOperator()); } - { UNREACHABLE_BAD_CASE_ANALYSIS } + {UNREACHABLE_BAD_CASE_ANALYSIS} #undef BINARY_OP_LOGICAL #undef BINARY_OP_INTEGRAL @@ -805,7 +814,7 @@ RamDomain Engine::execute(const Node* node, Context& ctxt) { case ram::NestedIntrinsicOp::FRANGE: return RUN_RANGE(RamFloat); } - { UNREACHABLE_BAD_CASE_ANALYSIS } + {UNREACHABLE_BAD_CASE_ANALYSIS} #undef RUN_RANGE ESAC(NestedIntrinsicOperator) @@ -1089,7 +1098,7 @@ RamDomain Engine::execute(const Node* node, Context& ctxt) { } } - { UNREACHABLE_BAD_CASE_ANALYSIS } + {UNREACHABLE_BAD_CASE_ANALYSIS} #undef COMPARE_NUMERIC #undef COMPARE_STRING diff --git a/src/interpreter/Engine.h b/src/interpreter/Engine.h index d4dcb01315a..22293f1ecfb 100644 --- a/src/interpreter/Engine.h +++ b/src/interpreter/Engine.h @@ -57,14 +57,24 @@ class Engine { friend NodeGenerator; public: - Engine(ram::TranslationUnit& tUnit); + Engine(ram::TranslationUnit& tUnit, const std::size_t numThreads); /** @brief Execute the main program */ void executeMain(); + /** @brief Execute the subroutine program */ void executeSubroutine( const std::string& name, const std::vector& args, std::vector& ret); + /** @brief Return the global object this engine uses */ + Global& getGlobal(); + + /** @brief Return the string symbol table */ + SymbolTable& getSymbolTable(); + + /** @brief Return the record table */ + RecordTable& getRecordTable(); + private: /** @brief Generate intermediate representation from RAM */ void generateIR(); @@ -74,15 +84,9 @@ class Engine { void swapRelation(const std::size_t ramRel1, const std::size_t ramRel2); /** @brief Return a reference to the relation on the given index */ RelationHandle& getRelationHandle(const std::size_t idx); - /** @brief Return the string symbol table */ - SymbolTable& getSymbolTable() { - return symbolTable; - } - /** @brief Return the record table */ - RecordTable& getRecordTable(); /** @brief Return the ram::TranslationUnit */ ram::TranslationUnit& getTranslationUnit(); - /** @brief Execute the program */ + /** @brief Execute a specific node program */ RamDomain execute(const Node*, Context&); /** @brief Return method handler */ void* getMethodHandle(const std::string& method); @@ -167,6 +171,10 @@ class Engine { template RamDomain evalErase(Rel& rel, const Erase& shadow, Context& ctxt); + /** Program */ + ram::TranslationUnit& tUnit; + /** Global */ + Global& global; /** If profile is enable in this program */ const bool profileEnabled; const bool frequencyCounterEnabled; @@ -186,8 +194,6 @@ class Engine { std::map> reads; /** DLL */ std::vector dll; - /** Program */ - ram::TranslationUnit& tUnit; /** IndexAnalysis */ ram::analysis::IndexAnalysis& isa; /** Record Table Implementation*/ diff --git a/src/interpreter/Generator.cpp b/src/interpreter/Generator.cpp index 92d09f39ea5..b0f31db7d42 100644 --- a/src/interpreter/Generator.cpp +++ b/src/interpreter/Generator.cpp @@ -23,7 +23,7 @@ using NodePtr = Own; using NodePtrVec = std::vector; using RelationHandle = Own; -NodeGenerator::NodeGenerator(Engine& engine) : engine(engine) { +NodeGenerator::NodeGenerator(Engine& engine) : engine(engine), global(engine.getGlobal()) { visit(engine.tUnit.getProgram(), [&](const ram::Relation& relation) { assert(relationMap.find(relation.getName()) == relationMap.end() && "double-naming of relations"); relationMap[relation.getName()] = &relation; @@ -206,14 +206,14 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Negation& NodePtr NodeGenerator::visit_(type_identity, const ram::EmptinessCheck& emptiness) { std::size_t relId = encodeRelation(emptiness.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("EmptinessCheck", lookup(emptiness.getRelation())); + NodeType type = constructNodeType(global, "EmptinessCheck", lookup(emptiness.getRelation())); return mk(type, &emptiness, rel); } NodePtr NodeGenerator::visit_(type_identity, const ram::RelationSize& size) { std::size_t relId = encodeRelation(size.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("RelationSize", lookup(size.getRelation())); + NodeType type = constructNodeType(global, "RelationSize", lookup(size.getRelation())); return mk(type, &size, rel); } @@ -227,7 +227,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Exi } } const auto& ramRelation = lookup(exists.getRelation()); - NodeType type = constructNodeType("ExistenceCheck", ramRelation); + NodeType type = constructNodeType(global, "ExistenceCheck", ramRelation); return mk(type, &exists, isTotal, encodeView(&exists), std::move(superOp), ramRelation.isTemp(), ramRelation.getName()); } @@ -235,7 +235,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Exi NodePtr NodeGenerator::visit_( type_identity, const ram::ProvenanceExistenceCheck& provExists) { SuperInstruction superOp = getExistenceSuperInstInfo(provExists); - NodeType type = constructNodeType("ProvenanceExistenceCheck", lookup(provExists.getRelation())); + NodeType type = constructNodeType(global, "ProvenanceExistenceCheck", lookup(provExists.getRelation())); return mk(type, &provExists, dispatch(*(--provExists.getChildNodes().end())), encodeView(&provExists), std::move(superOp)); } @@ -281,7 +281,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Scan& scan) { orderingContext.addTupleWithDefaultOrder(scan.getTupleId(), scan); std::size_t relId = encodeRelation(scan.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("Scan", lookup(scan.getRelation())); + NodeType type = constructNodeType(global, "Scan", lookup(scan.getRelation())); return mk(type, &scan, rel, visit_(type_identity(), scan)); } @@ -289,7 +289,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Paral orderingContext.addTupleWithDefaultOrder(pScan.getTupleId(), pScan); std::size_t relId = encodeRelation(pScan.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelScan", lookup(pScan.getRelation())); + NodeType type = constructNodeType(global, "ParallelScan", lookup(pScan.getRelation())); auto res = mk(type, &pScan, rel, visit_(type_identity(), pScan)); res->setViewContext(parentQueryViewContext); return res; @@ -298,7 +298,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Paral NodePtr NodeGenerator::visit_(type_identity, const ram::IndexScan& iScan) { orderingContext.addTupleWithIndexOrder(iScan.getTupleId(), iScan); SuperInstruction indexOperation = getIndexSuperInstInfo(iScan); - NodeType type = constructNodeType("IndexScan", lookup(iScan.getRelation())); + NodeType type = constructNodeType(global, "IndexScan", lookup(iScan.getRelation())); return mk(type, &iScan, nullptr, visit_(type_identity(), iScan), encodeView(&iScan), std::move(indexOperation)); } @@ -308,7 +308,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram:: SuperInstruction indexOperation = getIndexSuperInstInfo(piscan); std::size_t relId = encodeRelation(piscan.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelIndexScan", lookup(piscan.getRelation())); + NodeType type = constructNodeType(global, "ParallelIndexScan", lookup(piscan.getRelation())); auto res = mk(type, &piscan, rel, visit_(type_identity(), piscan), encodeIndexPos(piscan), std::move(indexOperation)); res->setViewContext(parentQueryViewContext); @@ -319,7 +319,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::IfExists& orderingContext.addTupleWithDefaultOrder(ifexists.getTupleId(), ifexists); std::size_t relId = encodeRelation(ifexists.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("IfExists", lookup(ifexists.getRelation())); + NodeType type = constructNodeType(global, "IfExists", lookup(ifexists.getRelation())); return mk(type, &ifexists, rel, dispatch(ifexists.getCondition()), visit_(type_identity(), ifexists)); } @@ -328,7 +328,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::P orderingContext.addTupleWithDefaultOrder(pIfExists.getTupleId(), pIfExists); std::size_t relId = encodeRelation(pIfExists.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelIfExists", lookup(pIfExists.getRelation())); + NodeType type = constructNodeType(global, "ParallelIfExists", lookup(pIfExists.getRelation())); auto res = mk(type, &pIfExists, rel, dispatch(pIfExists.getCondition()), visit_(type_identity(), pIfExists)); res->setViewContext(parentQueryViewContext); @@ -338,7 +338,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::P NodePtr NodeGenerator::visit_(type_identity, const ram::IndexIfExists& iIfExists) { orderingContext.addTupleWithIndexOrder(iIfExists.getTupleId(), iIfExists); SuperInstruction indexOperation = getIndexSuperInstInfo(iIfExists); - NodeType type = constructNodeType("IndexIfExists", lookup(iIfExists.getRelation())); + NodeType type = constructNodeType(global, "IndexIfExists", lookup(iIfExists.getRelation())); return mk(type, &iIfExists, nullptr, dispatch(iIfExists.getCondition()), visit_(type_identity(), iIfExists), encodeView(&iIfExists), std::move(indexOperation)); @@ -350,7 +350,7 @@ NodePtr NodeGenerator::visit_( SuperInstruction indexOperation = getIndexSuperInstInfo(piIfExists); std::size_t relId = encodeRelation(piIfExists.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelIndexIfExists", lookup(piIfExists.getRelation())); + NodeType type = constructNodeType(global, "ParallelIndexIfExists", lookup(piIfExists.getRelation())); auto res = mk(type, &piIfExists, rel, dispatch(piIfExists.getCondition()), dispatch(piIfExists.getOperation()), encodeIndexPos(piIfExists), std::move(indexOperation)); res->setViewContext(parentQueryViewContext); @@ -399,7 +399,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Aggregat NodePtr nested = visit_(type_identity(), aggregate); std::size_t relId = encodeRelation(aggregate.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("Aggregate", lookup(aggregate.getRelation())); + NodeType type = constructNodeType(global, "Aggregate", lookup(aggregate.getRelation())); /* Resolve functor to actual function pointer now */ void* functionPtr = resolveFunctionPointers(aggregate); @@ -418,7 +418,7 @@ NodePtr NodeGenerator::visit_( NodePtr nested = visit_(type_identity(), pAggregate); std::size_t relId = encodeRelation(pAggregate.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelAggregate", lookup(pAggregate.getRelation())); + NodeType type = constructNodeType(global, "ParallelAggregate", lookup(pAggregate.getRelation())); /* Resolve functor to actual function pointer now */ void* functionPtr = resolveFunctionPointers(pAggregate); auto res = mk(type, &pAggregate, rel, std::move(expr), std::move(cond), @@ -438,7 +438,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Ind NodePtr nested = visit_(type_identity(), iAggregate); std::size_t relId = encodeRelation(iAggregate.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("IndexAggregate", lookup(iAggregate.getRelation())); + NodeType type = constructNodeType(global, "IndexAggregate", lookup(iAggregate.getRelation())); /* Resolve functor to actual function pointer now */ void* functionPtr = resolveFunctionPointers(iAggregate); return mk(type, &iAggregate, rel, std::move(expr), std::move(cond), std::move(nested), @@ -456,7 +456,7 @@ NodePtr NodeGenerator::visit_( NodePtr nested = visit_(type_identity(), piAggregate); std::size_t relId = encodeRelation(piAggregate.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("ParallelIndexAggregate", lookup(piAggregate.getRelation())); + NodeType type = constructNodeType(global, "ParallelIndexAggregate", lookup(piAggregate.getRelation())); /* Resolve functor to actual function pointer now */ void* functionPtr = resolveFunctionPointers(piAggregate); auto res = mk(type, &piAggregate, rel, std::move(expr), std::move(cond), @@ -478,7 +478,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Guar SuperInstruction superOp = getInsertSuperInstInfo(guardedInsert); std::size_t relId = encodeRelation(guardedInsert.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("GuardedInsert", lookup(guardedInsert.getRelation())); + NodeType type = constructNodeType(global, "GuardedInsert", lookup(guardedInsert.getRelation())); auto condition = guardedInsert.getCondition(); return mk(type, &guardedInsert, rel, std::move(superOp), dispatch(*condition)); } @@ -487,7 +487,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Insert& ins SuperInstruction superOp = getInsertSuperInstInfo(insert); std::size_t relId = encodeRelation(insert.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("Insert", lookup(insert.getRelation())); + NodeType type = constructNodeType(global, "Insert", lookup(insert.getRelation())); return mk(type, &insert, rel, std::move(superOp)); } @@ -495,7 +495,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::Erase& erase SuperInstruction superOp = getEraseSuperInstInfo(erase); std::size_t relId = encodeRelation(erase.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("Erase", lookup(erase.getRelation())); + NodeType type = constructNodeType(global, "Erase", lookup(erase.getRelation())); return mk(type, &erase, rel, std::move(superOp)); } @@ -558,7 +558,7 @@ NodePtr NodeGenerator::visit_(type_identity, const ram::DebugInf NodePtr NodeGenerator::visit_(type_identity, const ram::Clear& clear) { std::size_t relId = encodeRelation(clear.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("Clear", lookup(clear.getRelation())); + NodeType type = constructNodeType(global, "Clear", lookup(clear.getRelation())); return mk(type, &clear, rel); } @@ -566,7 +566,7 @@ NodePtr NodeGenerator::visit_( type_identity, const ram::EstimateJoinSize& estimateJoinSize) { std::size_t relId = encodeRelation(estimateJoinSize.getRelation()); auto rel = getRelationHandle(relId); - NodeType type = constructNodeType("EstimateJoinSize", lookup(estimateJoinSize.getRelation())); + NodeType type = constructNodeType(global, "EstimateJoinSize", lookup(estimateJoinSize.getRelation())); return mk(type, &estimateJoinSize, rel, encodeIndexPos(estimateJoinSize)); } diff --git a/src/interpreter/Generator.h b/src/interpreter/Generator.h index 34fa448e988..6d500eaac97 100644 --- a/src/interpreter/Generator.h +++ b/src/interpreter/Generator.h @@ -366,5 +366,7 @@ class NodeGenerator : public ram::Visitor> { OrderingContext orderingContext = OrderingContext(*this); /** Reference to the engine instance */ Engine& engine; + /** Reference to global */ + Global& global; }; } // namespace souffle::interpreter diff --git a/src/interpreter/Node.h b/src/interpreter/Node.h index 84a30dd456d..cbc40926972 100644 --- a/src/interpreter/Node.h +++ b/src/interpreter/Node.h @@ -140,8 +140,8 @@ enum NodeType { * * Add reflective from string to NodeType. */ -inline NodeType constructNodeType(std::string tokBase, const ram::Relation& rel) { - static bool isProvenance = Global::config().has("provenance"); +inline NodeType constructNodeType(Global& glb, std::string tokBase, const ram::Relation& rel) { + const bool isProvenance = glb.config().has("provenance"); static const std::unordered_map map = { FOR_EACH_INTERPRETER_TOKEN(SINGLE_TOKEN_ENTRY, EXPAND_TOKEN_ENTRY) diff --git a/src/interpreter/tests/interpreter_relation_test.cpp b/src/interpreter/tests/interpreter_relation_test.cpp index 6d7bfdfe8e4..b77d8dc32a8 100644 --- a/src/interpreter/tests/interpreter_relation_test.cpp +++ b/src/interpreter/tests/interpreter_relation_test.cpp @@ -20,7 +20,7 @@ #include "interpreter/Relation.h" #include "ram/analysis/Index.h" #include "souffle/SouffleInterface.h" -#include "souffle/SymbolTable.h" +#include "souffle/datastructure/SymbolTableImpl.h" #include #include #include diff --git a/src/interpreter/tests/ram_arithmetic_test.cpp b/src/interpreter/tests/ram_arithmetic_test.cpp index 728b56f21d3..a79171d3491 100644 --- a/src/interpreter/tests/ram_arithmetic_test.cpp +++ b/src/interpreter/tests/ram_arithmetic_test.cpp @@ -53,7 +53,8 @@ RamDomain evalExpression(Own expression) { VecOwn returnValues; returnValues.emplace_back(std::move(expression)); - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); Own query = mk(mk(std::move(returnValues))); std::map> subs; subs.insert(std::make_pair("test", std::move(query))); @@ -62,12 +63,12 @@ RamDomain evalExpression(Own expression) { Own prog = mk(std::move(rels), mk(), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::string name("test"); std::vector ret; diff --git a/src/interpreter/tests/ram_relation_test.cpp b/src/interpreter/tests/ram_relation_test.cpp index 5fa09128714..d8f24775a13 100644 --- a/src/interpreter/tests/ram_relation_test.cpp +++ b/src/interpreter/tests/ram_relation_test.cpp @@ -56,7 +56,8 @@ using json11::Json; const std::string testInterpreterStore( std::vector attribs, std::vector attribsTypes, VecOwn exprs) { - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); const std::size_t arity = attribs.size(); @@ -81,12 +82,12 @@ const std::string testInterpreterStore( Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -237,7 +238,8 @@ TEST(IO_store, SignedChangedDelimiter) { const std::size_t len = randomNumbers.size(); const std::string delimiter{", "}; - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -275,12 +277,12 @@ TEST(IO_store, SignedChangedDelimiter) { Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -310,7 +312,8 @@ TEST(IO_store, SignedChangedDelimiter) { } TEST(IO_store, MixedTypes) { - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -330,7 +333,7 @@ TEST(IO_store, MixedTypes) { std::map ioDirs = std::map(dirs); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); VecOwn exprs; RamFloat floatValue = 27.75; @@ -347,10 +350,10 @@ TEST(IO_store, MixedTypes) { std::map> subs; Own prog = mk(std::move(rels), std::move(main), std::move(subs)); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -382,7 +385,8 @@ TEST(IO_load, Signed) { std::istringstream testInput("5 3"); std::cin.rdbuf(testInput.rdbuf()); - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -411,12 +415,12 @@ TEST(IO_load, Signed) { Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -442,7 +446,8 @@ TEST(IO_load, Float) { std::istringstream testInput("0.5 0.5"); std::cin.rdbuf(testInput.rdbuf()); - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -471,12 +476,12 @@ TEST(IO_load, Float) { Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -502,7 +507,8 @@ TEST(IO_load, Unsigned) { std::istringstream testInput("6 6"); std::cin.rdbuf(testInput.rdbuf()); - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -531,12 +537,12 @@ TEST(IO_load, Unsigned) { Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; @@ -562,7 +568,8 @@ TEST(IO_load, MixedTypesLoad) { std::istringstream testInput("meow -3 3 0.5"); std::cin.rdbuf(testInput.rdbuf()); - Global::config().set("jobs", "1"); + Global glb; + glb.config().set("jobs", "1"); VecOwn rels; @@ -591,12 +598,12 @@ TEST(IO_load, MixedTypesLoad) { Own prog = mk(std::move(rels), std::move(main), std::move(subs)); ErrorReport errReport; - DebugReport debugReport; + DebugReport debugReport(glb); - TranslationUnit translationUnit(std::move(prog), errReport, debugReport); + TranslationUnit translationUnit(glb, std::move(prog), errReport, debugReport); // configure and execute interpreter - Own interpreter = mk(translationUnit); + Own interpreter = mk(translationUnit, 1); std::streambuf* oldCoutStreambuf = std::cout.rdbuf(); std::ostringstream sout; diff --git a/src/main.cpp b/src/main.cpp index 39cdbb6a366..eba0866f888 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,14 +128,14 @@ namespace souffle { /** * Executes a binary file. */ -[[noreturn]] void executeBinaryAndExit(const std::string& binaryFilename) { +[[noreturn]] void executeBinaryAndExit(Global& glb, const std::string& binaryFilename) { assert(!binaryFilename.empty() && "binary filename cannot be blank"); std::map env; - if (Global::config().has("library-dir")) { + if (glb.config().has("library-dir")) { auto escapeLdPath = [](auto&& xs) { return escape(xs, {':', ' '}, "\\"); }; - auto ld_path = toString(join( - map(Global::config().getMany("library-dir"), escapeLdPath), std::string(1, PATHdelimiter))); + auto ld_path = toString( + join(map(glb.config().getMany("library-dir"), escapeLdPath), std::string(1, PATHdelimiter))); #if defined(_MSC_VER) std::size_t l; std::wstring env_path(ld_path.length() + 1, L' '); @@ -161,7 +161,7 @@ namespace souffle { auto exit = execute(binaryFilename, {}, env); if (!exit) throw std::invalid_argument("failed to execute `" + binaryFilename + "`"); - if (!Global::config().has("dl-program")) { + if (!glb.config().has("dl-program")) { remove(binaryFilename.c_str()); remove((binaryFilename + ".cpp").c_str()); } @@ -172,24 +172,25 @@ namespace souffle { /** * Compiles the given source file to a binary file. */ -void compileToBinary(const std::string& command, std::vector& sourceFilenames, fs::path binary) { +void compileToBinary( + Global& glb, const std::string& command, std::vector& sourceFilenames, fs::path binary) { std::vector argv; argv.push_back(command); - if (Global::config().has("swig")) { + if (glb.config().has("swig")) { argv.push_back("-s"); - argv.push_back(Global::config().get("swig")); + argv.push_back(glb.config().get("swig")); } - for (auto&& path : Global::config().getMany("library-dir")) { + for (auto&& path : glb.config().getMany("library-dir")) { // The first entry may be blank if (path.empty()) { continue; } argv.push_back(tfm::format("-L%s", path)); } - for (auto&& library : Global::config().getMany("libraries")) { + for (auto&& library : glb.config().getMany("libraries")) { // The first entry may be blank if (library.empty()) { continue; @@ -362,11 +363,11 @@ class MCPPPreprocInput : public PreprocInput { } }; -static WarnSet process_warn_opts(void) { +static WarnSet process_warn_opts(const Global& glb) { WarnSet warns; - if (!Global::config().has("no-warn")) { - if (Global::config().has("warn")) { - for (auto&& option : Global::config().getMany("warn")) { + if (!glb.config().has("no-warn")) { + if (glb.config().has("warn")) { + for (auto&& option : glb.config().getMany("warn")) { if (option == "all") { warns.set(); } else { @@ -377,8 +378,8 @@ static WarnSet process_warn_opts(void) { } } } - if (Global::config().has("wno")) { - for (auto&& option : Global::config().getMany("wno")) { + if (glb.config().has("wno")) { + for (auto&& option : glb.config().getMany("wno")) { if (option == "none") { // default } else if (option == "all") { warns.reset(); @@ -394,7 +395,7 @@ static WarnSet process_warn_opts(void) { return warns; } -int main(int argc, char** argv) { +int main(Global& glb, int argc, char** argv) { /* Time taking for overall runtime */ auto souffle_start = std::chrono::high_resolution_clock::now(); @@ -518,15 +519,15 @@ int main(int argc, char** argv) { {"legacy", '\6', "", "", false, "Enable legacy support."}, {"preprocessor", '\7', "CMD", "", false, "C preprocessor to use."}, {"no-preprocessor", 10, "", "", false, "Do not use a C preprocessor."}}; - Global::config().processArgs(argc, argv, header.str(), versionFooter, options); + glb.config().processArgs(argc, argv, header.str(), versionFooter, options); // ------ command line arguments ------------- // Take in pragma options from the command line - if (Global::config().has("pragma")) { - ast::transform::PragmaChecker::Merger merger; + if (glb.config().has("pragma")) { + ast::transform::PragmaChecker::Merger merger(glb); - for (auto&& option : Global::config().getMany("pragma")) { + for (auto&& option : glb.config().getMany("pragma")) { // TODO: escape sequences for `:` to allow `:` in a pragma key? std::size_t splitPoint = option.find(':'); @@ -540,67 +541,67 @@ int main(int argc, char** argv) { } /* for the version option, if given print the version text then exit */ - if (Global::config().has("version")) { + if (glb.config().has("version")) { std::cout << versionFooter << std::endl; return 0; } - Global::config().set("version", PACKAGE_VERSION); + glb.config().set("version", PACKAGE_VERSION); /* for the help option, if given simply print the help text then exit */ - if (Global::config().has("help")) { - std::cout << Global::config().help(); + if (glb.config().has("help")) { + std::cout << glb.config().help(); return 0; } - if (!Global::config().has("")) { + if (!glb.config().has("")) { std::cerr << "No datalog file specified.\n"; return 0; } /* check that datalog program exists */ - if (!existFile(Global::config().get(""))) { - throw std::runtime_error("cannot open file " + std::string(Global::config().get(""))); + if (!existFile(glb.config().get(""))) { + throw std::runtime_error("cannot open file " + std::string(glb.config().get(""))); } /* for the jobs option, to determine the number of threads used */ #ifdef _OPENMP - if (isNumber(Global::config().get("jobs").c_str())) { - if (std::stoi(Global::config().get("jobs")) < 1) { + if (isNumber(glb.config().get("jobs").c_str())) { + if (std::stoi(glb.config().get("jobs")) < 1) { throw std::runtime_error("-j/--jobs may only be set to 'auto' or an integer greater than 0."); } } else { - if (!Global::config().has("jobs", "auto")) { + if (!glb.config().has("jobs", "auto")) { throw std::runtime_error("-j/--jobs may only be set to 'auto' or an integer greater than 0."); } // set jobs to zero to indicate the synthesiser and interpreter to use the system default. - Global::config().set("jobs", "0"); + glb.config().set("jobs", "0"); } #else // Check that -j option has not been changed from the default - if (Global::config().get("jobs") != "1" && !Global::config().has("no-warn")) { + if (glb.config().get("jobs") != "1" && !glb.config().has("no-warn")) { std::cerr << "\nThis installation of Souffle does not support concurrent jobs.\n"; } #endif /* if an output directory is given, check it exists */ - if (Global::config().has("output-dir") && !Global::config().has("output-dir", "-") && - !existDir(Global::config().get("output-dir")) && - !(Global::config().has("generate") || - (Global::config().has("dl-program") && !Global::config().has("compile")))) { + if (glb.config().has("output-dir") && !glb.config().has("output-dir", "-") && + !existDir(glb.config().get("output-dir")) && + !(glb.config().has("generate") || + (glb.config().has("dl-program") && !glb.config().has("compile")))) { throw std::runtime_error( - "output directory " + Global::config().get("output-dir") + " does not exists"); + "output directory " + glb.config().get("output-dir") + " does not exists"); } /* verify all input directories exist (racey, but gives nicer error messages for common mistakes) */ - for (auto&& dir : Global::config().getMany("include-dir")) { + for (auto&& dir : glb.config().getMany("include-dir")) { if (!existDir(dir)) throw std::runtime_error("include directory `" + dir + "` does not exist"); } /* collect all macro definitions for the pre-processor */ - if (Global::config().has("macro")) { + if (glb.config().has("macro")) { std::string currentMacro = ""; std::string allMacros = ""; - for (const char& ch : Global::config().get("macro")) { + for (const char& ch : glb.config().get("macro")) { if (ch == ' ') { allMacros += " -D"; allMacros += currentMacro; @@ -610,16 +611,16 @@ int main(int argc, char** argv) { } } allMacros += " -D" + currentMacro; - Global::config().set("macro", allMacros); + glb.config().set("macro", allMacros); } - if (Global::config().has("live-profile") && !Global::config().has("profile")) { - Global::config().set("profile"); + if (glb.config().has("live-profile") && !glb.config().has("profile")) { + glb.config().set("profile"); } /* if emit-statistics is set then check that the profiler is also set */ - if (Global::config().has("emit-statistics")) { - if (!Global::config().has("profile")) + if (glb.config().has("emit-statistics")) { + if (!glb.config().has("profile")) throw std::runtime_error("must be profiling to use emit-statistics"); } @@ -631,8 +632,8 @@ int main(int argc, char** argv) { /** * Ensure that code generation is enabled if using SWIG interface option. */ - if (Global::config().has("swig") && !Global::config().has("generate")) { - Global::config().set("generate", simpleName(Global::config().get(""))); + if (glb.config().has("swig") && !glb.config().has("generate")) { + glb.config().set("generate", simpleName(glb.config().get(""))); } // ------ start souffle ------------- @@ -643,28 +644,28 @@ int main(int argc, char** argv) { throw std::runtime_error("failed to determine souffle executable path"); } - const std::filesystem::path InputPath(Global::config().get("")); + const std::filesystem::path InputPath(glb.config().get("")); std::unique_ptr Input; - const bool use_preprocessor = !Global::config().has("no-preprocessor"); + const bool use_preprocessor = !glb.config().has("no-preprocessor"); if (use_preprocessor) { - if (Global::config().has("preprocessor")) { - auto cmd = Global::config().get("preprocessor"); + if (glb.config().has("preprocessor")) { + auto cmd = glb.config().get("preprocessor"); if (cmd == "gcc") { - Input = std::make_unique(InputPath, Global::config()); + Input = std::make_unique(InputPath, glb.config()); } else if (cmd == "mcpp") { - Input = std::make_unique(InputPath, Global::config()); + Input = std::make_unique(InputPath, glb.config()); } else { - Input = std::make_unique(InputPath, Global::config(), cmd); + Input = std::make_unique(InputPath, glb.config(), cmd); } } else if (MCPPPreprocInput::available()) { // mcpp fallback - Input = std::make_unique(InputPath, Global::config()); + Input = std::make_unique(InputPath, glb.config()); } else if (GCCPreprocInput::available()) { // gcc fallback - Input = std::make_unique(InputPath, Global::config()); + Input = std::make_unique(InputPath, glb.config()); } else { throw std::runtime_error("failed to locate mcpp or gcc pre-processors"); } } else { - Input = std::make_unique(Global::config().get("")); + Input = std::make_unique(glb.config().get("")); } /* Time taking for parsing */ @@ -673,26 +674,26 @@ int main(int argc, char** argv) { // ------- parse program ------------- // parse file - ErrorReport errReport(process_warn_opts()); + ErrorReport errReport(process_warn_opts(glb)); DebugReport debugReport; Own astTranslationUnit = ParserDriver::parseTranslationUnit( - InputPath.string(), Input->getInputStream(), errReport, debugReport); + glb, InputPath.string(), Input->getInputStream(), errReport, debugReport); Input->endInput(); /* Report run-time of the parser if verbose flag is set */ - if (Global::config().has("verbose")) { + if (glb.config().has("verbose")) { auto parser_end = std::chrono::high_resolution_clock::now(); std::cout << "Parse time: " << std::chrono::duration(parser_end - parser_start).count() << "sec\n"; } - auto hasShowOpt = [&](auto&&... kind) { return (Global::config().has("show", kind) || ...); }; + auto hasShowOpt = [&](auto&&... kind) { return (glb.config().has("show", kind) || ...); }; // `--show parse-errors` is special in that it (ab?)used the return code to specify the # of errors. // Other `--show` modes can be used in conjunction with each other. if (hasShowOpt("parse-errors")) { - if (1 < Global::config().getMany("show").size()) { + if (1 < glb.config().getMany("show").size()) { std::cerr << "WARNING: `--show parse-errors` inhibits other `--show` actions.\n"; } @@ -711,7 +712,7 @@ int main(int argc, char** argv) { if (hasShowOpt("initial-ast", "initial-datalog")) { std::cout << astTranslationUnit->getProgram() << std::endl; // no other show options specified -> bail, we're done. - if (Global::config().getMany("show").size() == 1) return 0; + if (glb.config().getMany("show").size() == 1) return 0; } /* construct the transformation pipeline */ @@ -728,7 +729,7 @@ int main(int argc, char** argv) { // Magic-Set pipeline auto magicPipeline = mk( mk( - Global::config().has("magic-transform"), mk()), + glb.config().has("magic-transform"), mk()), mk(), mk(), mk(), mk(), @@ -741,7 +742,7 @@ int main(int argc, char** argv) { mk()); // Provenance pipeline - auto provenancePipeline = mk(Global::config().has("provenance"), + auto provenancePipeline = mk(glb.config().has("provenance"), mk(mk(), mk())); @@ -783,15 +784,15 @@ int main(int argc, char** argv) { mk()); // Disable unwanted transformations - if (Global::config().has("disable-transformers")) { + if (glb.config().has("disable-transformers")) { std::vector givenTransformers = - splitString(Global::config().get("disable-transformers"), ','); + splitString(glb.config().get("disable-transformers"), ','); pipeline->disableTransformers( std::set(givenTransformers.begin(), givenTransformers.end())); } // Set up the debug report if necessary - if (Global::config().has("debug-report")) { + if (glb.config().has("debug-report")) { auto parser_end = std::chrono::high_resolution_clock::now(); std::stringstream ss; @@ -802,7 +803,7 @@ int main(int argc, char** argv) { // Add config ss << "(\n"; - ss << join(Global::config().data(), ",\n", [](std::ostream& out, const auto& arg) { + ss << join(glb.config().data(), ",\n", [](std::ostream& out, const auto& arg) { out << " \"" << arg.first << "\" -> \"" << arg.second << '"'; }); ss << "\n)"; @@ -818,7 +819,7 @@ int main(int argc, char** argv) { } // Toggle pipeline verbosity - pipeline->setVerbosity(Global::config().has("verbose")); + pipeline->setVerbosity(glb.config().has("verbose")); // Apply all the transformations pipeline->apply(*astTranslationUnit); @@ -859,13 +860,13 @@ int main(int argc, char** argv) { } // bail if we've nothing else left to show - if (Global::config().has("show") && !hasShowOpt("initial-ram", "transformed-ram")) return 0; + if (glb.config().has("show") && !hasShowOpt("initial-ram", "transformed-ram")) return 0; // ------- execution ------------- /* translate AST to RAM */ debugReport.startSection(); auto translationStrategy = - Global::config().has("provenance") + glb.config().has("provenance") ? mk() : mk(); auto unitTranslator = Own(translationStrategy->createUnitTranslator()); @@ -893,7 +894,7 @@ int main(int argc, char** argv) { mk(), mk(mk()), mk( // job count of 0 means all cores are used. - []() -> bool { return std::stoi(Global::config().get("jobs")) != 1; }, + [&]() -> bool { return std::stoi(glb.config().get("jobs")) != 1; }, mk()), mk()); @@ -910,15 +911,15 @@ int main(int argc, char** argv) { return 0; } - const bool execute_mode = Global::config().has("compile") || Global::config().has("compile-many"); - const bool compile_mode = Global::config().has("dl-program"); - const bool generate_mode = Global::config().has("generate"); - const bool generate_many_mode = Global::config().has("generate-many"); + const bool execute_mode = glb.config().has("compile") || glb.config().has("compile-many"); + const bool compile_mode = glb.config().has("dl-program"); + const bool generate_mode = glb.config().has("generate"); + const bool generate_many_mode = glb.config().has("generate-many"); const bool must_interpret = !execute_mode && !compile_mode && !generate_mode && !generate_many_mode && - !Global::config().has("swig"); + !glb.config().has("swig"); const bool must_execute = execute_mode; - const bool must_compile = must_execute || compile_mode || Global::config().has("swig"); + const bool must_compile = must_execute || compile_mode || glb.config().has("swig"); try { if (must_interpret) { @@ -926,7 +927,7 @@ int main(int argc, char** argv) { std::thread profiler; // Start up profiler if needed - if (Global::config().has("live-profile")) { + if (glb.config().has("live-profile")) { #ifdef _MSC_VER throw("No live-profile on Windows\n."); #else @@ -935,28 +936,30 @@ int main(int argc, char** argv) { } // configure and execute interpreter - Own interpreter(mk(*ramTranslationUnit)); + const std::size_t numThreadsOrZero = std::stoi(glb.config().get("jobs")); + Own interpreter( + mk(*ramTranslationUnit, numThreadsOrZero)); interpreter->executeMain(); // If the profiler was started, join back here once it exits. if (profiler.joinable()) { profiler.join(); } - if (Global::config().has("provenance")) { + if (glb.config().has("provenance")) { #ifdef _MSC_VER throw("No explain/explore provenance on Windows\n."); #else // only run explain interface if interpreted interpreter::ProgInterface interface(*interpreter); - if (Global::config().get("provenance") == "explain") { + if (glb.config().get("provenance") == "explain") { explain(interface, false); - } else if (Global::config().get("provenance") == "explore") { + } else if (glb.config().get("provenance") == "explore") { explain(interface, true); } #endif } } else { // ------- compiler ------------- - // int jobs = std::stoi(Global::config().get("jobs")); + // int jobs = std::stoi(glb.config().get("jobs")); // jobs = (jobs <= 0 ? MAX_THREADS : jobs); auto synthesiser = mk(/*static_cast(jobs),*/ *ramTranslationUnit); @@ -964,16 +967,16 @@ int main(int argc, char** argv) { // Find the base filename for code generation and execution std::string baseFilename; if (compile_mode) { - baseFilename = Global::config().get("dl-program"); + baseFilename = glb.config().get("dl-program"); } else if (generate_mode) { - baseFilename = Global::config().get("generate"); + baseFilename = glb.config().get("generate"); // trim .cpp extension if it exists if (baseFilename.size() >= 4 && baseFilename.substr(baseFilename.size() - 4) == ".cpp") { baseFilename = baseFilename.substr(0, baseFilename.size() - 4); } } else if (generate_many_mode) { - baseFilename = Global::config().get("generate-many"); + baseFilename = glb.config().get("generate-many"); } else { baseFilename = tempFile(); } @@ -988,18 +991,19 @@ int main(int argc, char** argv) { bool withSharedLibrary; auto synthesisStart = std::chrono::high_resolution_clock::now(); - const bool emitToStdOut = Global::config().has("generate", "-"); + const bool emitToStdOut = glb.config().has("generate", "-"); const bool emitMultipleFiles = - Global::config().has("generate-many") || Global::config().has("compile-many"); + glb.config().has("generate-many") || glb.config().has("compile-many"); synthesiser::GenDb db; synthesiser->generateCode(db, baseIdentifier, withSharedLibrary); std::vector srcFiles; - if (emitToStdOut) + + if (emitToStdOut) { db.emitSingleFile(std::cout); - else if (emitMultipleFiles) { - fs::path directory = Global::config().has("generate-many") - ? fs::path(Global::config().get("generate-many")) + } else if (emitMultipleFiles) { + fs::path directory = glb.config().has("generate-many") + ? fs::path(glb.config().get("generate-many")) : fs::temp_directory_path() / baseIdentifier; std::string mainClass = db.emitMultipleFilesInDir(directory, srcFiles); binaryFilename = (directory / fs::path(mainClass)).string(); @@ -1010,18 +1014,18 @@ int main(int argc, char** argv) { os.close(); srcFiles.push_back(fs::path(sourceFilename)); } - if (Global::config().has("verbose")) { + if (glb.config().has("verbose")) { auto synthesisEnd = std::chrono::high_resolution_clock::now(); std::cout << "Synthesis time: " << std::chrono::duration(synthesisEnd - synthesisStart).count() << "sec\n"; } if (withSharedLibrary) { - if (!Global::config().has("libraries")) { - Global::config().set("libraries", "functors"); + if (!glb.config().has("libraries")) { + glb.config().set("libraries", "functors"); } - if (!Global::config().has("library-dir")) { - Global::config().set("library-dir", "."); + if (!glb.config().has("library-dir")) { + glb.config().set("library-dir", "."); } } @@ -1032,10 +1036,10 @@ int main(int argc, char** argv) { auto t_bgn = std::chrono::high_resolution_clock::now(); fs::path output(binaryFilename); - compileToBinary(*souffle_compile, srcFiles, output); + compileToBinary(glb, *souffle_compile, srcFiles, output); auto t_end = std::chrono::high_resolution_clock::now(); - if (Global::config().has("verbose")) { + if (glb.config().has("verbose")) { std::cout << "Compilation time: " << std::chrono::duration(t_end - t_bgn).count() << "sec\n"; } @@ -1046,7 +1050,7 @@ int main(int argc, char** argv) { #if defined(_MSC_VER) binaryFilename += ".exe"; #endif - executeBinaryAndExit(binaryFilename); + executeBinaryAndExit(glb, binaryFilename); } } } catch (std::exception& e) { @@ -1055,7 +1059,7 @@ int main(int argc, char** argv) { } /* Report overall run-time in verbose mode */ - if (Global::config().has("verbose")) { + if (glb.config().has("verbose")) { auto souffle_end = std::chrono::high_resolution_clock::now(); std::cout << "Total time: " << std::chrono::duration(souffle_end - souffle_start).count() << "sec\n"; @@ -1067,5 +1071,6 @@ int main(int argc, char** argv) { } // end of namespace souffle int main(int argc, char** argv) { - return souffle::main(argc, argv); + souffle::Global glb; + return souffle::main(glb, argc, argv); } diff --git a/src/parser/ParserDriver.cpp b/src/parser/ParserDriver.cpp index 6c24dec4b25..15a6114ed02 100644 --- a/src/parser/ParserDriver.cpp +++ b/src/parser/ParserDriver.cpp @@ -51,7 +51,7 @@ namespace souffle { Own ParserDriver::parse( const std::string& filename, FILE* in, ErrorReport& errorReport, DebugReport& debugReport) { - translationUnit = mk(mk(), errorReport, debugReport); + translationUnit = mk(glb, mk(), errorReport, debugReport); yyscan_t scanner; ScannerInfo data; SrcLocation emptyLoc; @@ -70,7 +70,7 @@ Own ParserDriver::parse( Own ParserDriver::parse( const std::string& code, ErrorReport& errorReport, DebugReport& debugReport) { - translationUnit = mk(mk(), errorReport, debugReport); + translationUnit = mk(glb, mk(), errorReport, debugReport); ScannerInfo data; SrcLocation emptyLoc; @@ -87,15 +87,15 @@ Own ParserDriver::parse( return std::move(translationUnit); } -Own ParserDriver::parseTranslationUnit( - const std::string& filename, FILE* in, ErrorReport& errorReport, DebugReport& debugReport) { - ParserDriver parser; +Own ParserDriver::parseTranslationUnit(Global& glb, const std::string& filename, + FILE* in, ErrorReport& errorReport, DebugReport& debugReport) { + ParserDriver parser(glb); return parser.parse(filename, in, errorReport, debugReport); } Own ParserDriver::parseTranslationUnit( - const std::string& code, ErrorReport& errorReport, DebugReport& debugReport) { - ParserDriver parser; + Global& glb, const std::string& code, ErrorReport& errorReport, DebugReport& debugReport) { + ParserDriver parser(glb); return parser.parse(code, errorReport, debugReport); } @@ -208,14 +208,14 @@ void ParserDriver::addIoFromDeprecatedTag(ast::Relation& rel) { std::set ParserDriver::addDeprecatedTag( RelationTag tag, SrcLocation tagLoc, std::set tags) { - if (!Global::config().has("legacy")) { + if (!translationUnit->global().config().has("legacy")) { warning(WarnType::DeprecatedQualifier, tagLoc, tfm::format("Deprecated %s qualifier was used", tag)); } return addTag(tag, std::move(tagLoc), std::move(tags)); } Own ParserDriver::addDeprecatedCounter(SrcLocation tagLoc) { - if (!Global::config().has("legacy")) { + if (!translationUnit->global().config().has("legacy")) { warning(WarnType::DollarSign, tagLoc, "Deprecated $ symbol was used. Use functor 'autoinc()' instead."); } @@ -244,7 +244,7 @@ std::set ParserDriver::addTag(RelationTag tag, std::vector ParserDriver::mkDeprecatedSubType( ast::QualifiedName name, ast::QualifiedName baseTypeName, SrcLocation loc) { - if (!Global::config().has("legacy")) { + if (!translationUnit->global().config().has("legacy")) { warning(WarnType::DeprecatedTypeDecl, loc, "Deprecated type declaration used"); } return mk(std::move(name), std::move(baseTypeName), std::move(loc)); @@ -280,7 +280,7 @@ std::optional ParserDriver::searchIncludePath( } // search relative from include directories - for (auto&& includeDir : Global::config().getMany("include-dir")) { + for (auto&& includeDir : glb.config().getMany("include-dir")) { auto dir = std::filesystem::path(includeDir); if (dir.is_relative()) { dir = (std::filesystem::current_path() / includeDir); diff --git a/src/parser/ParserDriver.h b/src/parser/ParserDriver.h index 583166f9313..762ea141877 100644 --- a/src/parser/ParserDriver.h +++ b/src/parser/ParserDriver.h @@ -43,6 +43,7 @@ namespace souffle { class ParserDriver { public: + ParserDriver(Global& g) : glb(g) {} virtual ~ParserDriver() = default; void addRelation(Own r); @@ -70,10 +71,10 @@ class ParserDriver { const std::string& filename, FILE* in, ErrorReport& errorReport, DebugReport& debugReport); Own parse( const std::string& code, ErrorReport& errorReport, DebugReport& debugReport); + static Own parseTranslationUnit(Global& glb, const std::string& filename, FILE* in, + ErrorReport& errorReport, DebugReport& debugReport); static Own parseTranslationUnit( - const std::string& filename, FILE* in, ErrorReport& errorReport, DebugReport& debugReport); - static Own parseTranslationUnit( - const std::string& code, ErrorReport& errorReport, DebugReport& debugReport); + Global& glb, const std::string& code, ErrorReport& errorReport, DebugReport& debugReport); void warning(const WarnType warn, const SrcLocation& loc, const std::string& msg); void error(const SrcLocation& loc, const std::string& msg); @@ -93,6 +94,9 @@ class ParserDriver { std::set> VisitedLocations; std::deque> ScannedComments; + +private: + Global& glb; }; } // end of namespace souffle diff --git a/src/ram/TranslationUnit.cpp b/src/ram/TranslationUnit.cpp index 645893fe718..16aa8cac98c 100644 --- a/src/ram/TranslationUnit.cpp +++ b/src/ram/TranslationUnit.cpp @@ -8,12 +8,13 @@ #include "TranslationUnit.h" #include "Global.h" +#include "ram/Program.h" #include "souffle/utility/StringUtil.h" namespace souffle::ram { void TranslationUnit::logAnalysis(Analysis& analysis) const { - if (!Global::config().has("debug-report")) return; + if (!global().config().has("debug-report")) return; auto ss = toString(analysis); debugReport.addSection( diff --git a/src/ram/transform/MakeIndex.cpp b/src/ram/transform/MakeIndex.cpp index 5497c2374d0..d9748a7055b 100644 --- a/src/ram/transform/MakeIndex.cpp +++ b/src/ram/transform/MakeIndex.cpp @@ -90,9 +90,9 @@ ExpressionPair MakeIndexTransformer::getExpressionPair( ExpressionPair MakeIndexTransformer::getLowerUpperExpression(Condition* c, std::size_t& element, const std::optional& identifier, RelationRepresentation rep) { if (auto* binRelOp = as(c)) { - const bool interpreter = !Global::config().has("compile") && !Global::config().has("dl-program") && - !Global::config().has("generate") && - !Global::config().has("generate-many") && !Global::config().has("swig"); + const bool interpreter = !glb->config().has("compile") && !glb->config().has("dl-program") && + !glb->config().has("generate") && !glb->config().has("generate-many") && + !glb->config().has("swig"); bool provenance = rep == RelationRepresentation::PROVENANCE; bool btree = (rep == RelationRepresentation::BTREE || rep == RelationRepresentation::DEFAULT || rep == RelationRepresentation::BTREE_DELETE); @@ -478,7 +478,8 @@ Own MakeIndexTransformer::rewriteIndexScan(const IndexScan* iscan) { return nullptr; } -bool MakeIndexTransformer::makeIndex(Program& program) { +bool MakeIndexTransformer::makeIndex(Global& g, Program& program) { + glb = &g; bool changed = false; forEachQueryMap(program, [&](auto&& go, Own node) -> Own { if (const Scan* scan = as(node)) { diff --git a/src/ram/transform/MakeIndex.h b/src/ram/transform/MakeIndex.h index 55b799c5b2c..96cb4237521 100644 --- a/src/ram/transform/MakeIndex.h +++ b/src/ram/transform/MakeIndex.h @@ -126,7 +126,7 @@ class MakeIndexTransformer : public Transformer { * @param RAM program that is transformed * @result Flag that indicates whether the input program has changed */ - bool makeIndex(Program& program); + bool makeIndex(Global&, Program& program); protected: analysis::LevelAnalysis* rla{nullptr}; @@ -134,10 +134,12 @@ class MakeIndexTransformer : public Transformer { bool transform(TranslationUnit& translationUnit) override { rla = &translationUnit.getAnalysis(); relAnalysis = &translationUnit.getAnalysis(); - return makeIndex(translationUnit.getProgram()); + return makeIndex(translationUnit.global(), translationUnit.getProgram()); } analysis::RelationAnalysis* relAnalysis{nullptr}; + + Global* glb; }; } // namespace souffle::ram::transform diff --git a/src/ram/transform/Transformer.cpp b/src/ram/transform/Transformer.cpp index 9874a53c22c..6c56b72795c 100644 --- a/src/ram/transform/Transformer.cpp +++ b/src/ram/transform/Transformer.cpp @@ -31,8 +31,8 @@ namespace souffle::ram::transform { bool Transformer::apply(TranslationUnit& translationUnit) { - const bool debug = Global::config().has("debug-report"); - const bool verbose = Global::config().has("verbose"); + const bool debug = translationUnit.global().config().has("debug-report"); + const bool verbose = translationUnit.global().config().has("verbose"); std::string ramProgStrOld = debug ? toString(translationUnit.getProgram()) : ""; // invoke the transformation diff --git a/src/reports/DebugReport.cpp b/src/reports/DebugReport.cpp index a20d621a79c..d2a2aba7bf0 100644 --- a/src/reports/DebugReport.cpp +++ b/src/reports/DebugReport.cpp @@ -59,6 +59,19 @@ std::string replaceAll(std::string_view text, std::string_view key, std::string_ } } // namespace +DebugReport::DebugReport() : enabled(false), reportPath(), programName() {} + +DebugReport::DebugReport(Global& glb) { + enabled = !glb.config().get("debug-report").empty(); + if (enabled) { + reportPath = glb.config().get("debug-report"); + programName = glb.config().get(""); + } +} + +DebugReport::DebugReport(const std::string& report_path, const std::string& program_name) + : enabled(true), reportPath(report_path), programName(program_name) {} + void DebugReportSection::printIndex(std::ostream& out) const { out << "" << title << "\n"; out << "
    \n"; @@ -108,10 +121,18 @@ DebugReport::~DebugReport() { } void DebugReport::flush() { - auto&& dst = Global::config().get("debug-report"); - if (dst.empty() || empty()) return; + if (!enabled || empty()) return; + + std::ofstream(*reportPath) << *this; +} + +bool DebugReport::empty() const { + return sections.empty(); +} - std::ofstream(dst) << *this; +void DebugReport::addSection(DebugReportSection section) { + auto& buf = currentSubsections.empty() ? sections : currentSubsections.top(); + buf.emplace_back(std::move(section)); } static std::string CDATA(const std::string_view code) { @@ -151,7 +172,7 @@ void DebugReport::print(std::ostream& out) const { Souffle Debug Report ()--html--"; - out << Global::config().get("") << R"--html--() + out << *programName << R"--html--()