Skip to content

Commit

Permalink
Add a switch to namespace the generated code
Browse files Browse the repository at this point in the history
Fixes #2356.
  • Loading branch information
ruricolist committed Dec 2, 2022
1 parent 5e232fd commit bfd3e9b
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 46 deletions.
3 changes: 3 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,9 @@ int main(Global& glb, int argc, char** argv) {
{"generate-many", 'G', "DIR", "", false,
"Generate C++ source code in multiple files for the given Datalog program "
"and write it to <DIR>."},
{"generate-namespace", 'N', "NS", "", false,
"The namespace of generated C++ source code. Empty name denotes the anonymous "
"namespace."},
{"inline-exclude", '\x7', "RELATIONS", "", false,
"Prevent the given relations from being inlined. Overrides any `inline` qualifiers."},
{"swig", 's', "LANG", "", false,
Expand Down
75 changes: 46 additions & 29 deletions src/synthesiser/GenDb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void GenFunction::setNextInitializer(std::string field, std::string value) {
initializer.push_back(std::make_pair(field, value));
}

void GenFunction::declaration(std::ostream& o) const {
void GenFunction::declaration(const GenDb*, std::ostream& o) const {
o << retType << " " << name << "(" << join(args, ",", [&](auto& out, const auto arg) {
out << std::get<0>(arg) << " " << std::get<1>(arg);
std::optional<std::string> defaultValue = std::get<2>(arg);
Expand All @@ -67,7 +67,7 @@ void GenFunction::declaration(std::ostream& o) const {
}) << ");";
}

void GenFunction::definition(std::ostream& o) const {
void GenFunction::definition(const GenDb*, std::ostream& o) const {
o << retType << " ";
if (cl) {
o << cl->getName() << "::";
Expand Down Expand Up @@ -101,8 +101,10 @@ GenFunction& GenClass::addConstructor(Visibility v) {
return m;
}

void GenClass::declaration(std::ostream& o) const {
o << "namespace souffle {\n";
void GenClass::declaration(const GenDb* db, std::ostream& o) const {
o << "namespace " << db->getNS() << " {\n";

o << "using namespace souffle;\n";

o << "class " << name;
if (inheritance.size() > 0) {
Expand All @@ -116,7 +118,7 @@ void GenClass::declaration(std::ostream& o) const {

for (auto& fn : methods) {
auto& o = (fn->getVisibility() == Public) ? public_o : private_o;
fn->declaration(o);
fn->declaration(db, o);
o << "\n";
}
for (auto& [field, ty, v, init] : fields) {
Expand All @@ -130,21 +132,22 @@ void GenClass::declaration(std::ostream& o) const {
o << public_o.str();
o << private_o.str();
o << "};\n";
o << "} // namespace souffle\n";
o << "} // namespace " << db->getNS() << "\n";
}

void GenClass::definition(std::ostream& o) const {
void GenClass::definition(const GenDb* db, std::ostream& o) const {
if (ignoreUnusedArgumentWarning) {
o << "#ifdef _MSC_VER\n";
o << "#pragma warning(disable: 4100)\n";
o << "#endif // _MSC_VER\n";
}
o << "namespace souffle {\n";
o << "namespace " << db->getNS() << " {\n";
o << "using namespace souffle;\n";
for (auto& fn : methods) {
fn->definition(o);
fn->definition(db, o);
o << "\n";
}
o << "} // namespace souffle\n";
o << "} // namespace " << db->getNS() << "\n";

if (ignoreUnusedArgumentWarning) {
// restore unused argument warning
Expand All @@ -155,6 +158,18 @@ void GenClass::definition(std::ostream& o) const {
o << hiddenHooksStream.str() << "\n";
}

void GenDb::setNS(std::string ns) {
this->ns = ns;
}

std::string GenDb::getNS(const bool spaced) const {
if (spaced) {
return std::string{" "} + ns;
} else {
return ns;
}
}

GenClass& GenDb::getClass(std::string name, fs::path basename) {
classes.push_back(mk<GenClass>(name, basename));
GenClass& res = *classes.back();
Expand All @@ -174,22 +189,24 @@ GenDatastructure& GenDb::getDatastructure(
return res;
}

void GenDatastructure::declaration(std::ostream& o) const {
std::string ns = "souffle";
void GenDatastructure::declaration(const GenDb* db, std::ostream& o) const {
std::string ns = db->getNS(false);
if (namespace_name) {
ns += "::" + *namespace_name;
ns += (ns.empty() ? "" : "::") + *namespace_name;
}
o << "namespace " << ns << " {\n";
o << "using namespace souffle;\n";
o << declarationStream.str();
o << "} // namespace " << ns << " \n";
}

void GenDatastructure::definition(std::ostream& o) const {
std::string ns = "souffle";
void GenDatastructure::definition(const GenDb* db, std::ostream& o) const {
std::string ns = db->getNS(false);
if (namespace_name) {
ns += "::" + *namespace_name;
ns += (ns.empty() ? "" : "::") + *namespace_name;
}
o << "namespace " << ns << " {\n";
o << "using namespace souffle;\n";
o << definitionStream.str();
o << "} // namespace " << ns << " \n";
}
Expand Down Expand Up @@ -223,19 +240,19 @@ void GenDb::emitSingleFile(std::ostream& o) {
o << "}\n";
o << "} //namespace functors\n";
for (auto& ds : datastructures) {
ds->declaration(o);
ds->definition(o);
ds->declaration(this, o);
ds->definition(this, o);
}
std::size_t size = classes.size();
for (std::size_t i = 1; i < size - 1; i++) {
Own<GenClass>& cl = classes[i];
cl->declaration(o);
cl->definition(o);
cl->declaration(this, o);
cl->definition(this, o);
}
classes.front()->declaration(o);
classes.front()->definition(o);
classes.back()->declaration(o);
classes.back()->definition(o);
classes.front()->declaration(this, o);
classes.front()->definition(this, o);
classes.back()->declaration(this, o);
classes.back()->definition(this, o);
}

std::string GenDb::emitMultipleFilesInDir(fs::path dir, std::vector<fs::path>& toCompile) {
Expand Down Expand Up @@ -274,16 +291,16 @@ std::string GenDb::emitMultipleFilesInDir(fs::path dir, std::vector<fs::path>& t
std::ofstream hpp{rootDir / ds->fileBaseName().concat(".hpp")};
std::ofstream cpp{rootDir / ds->fileBaseName().concat(".cpp")};
genHeader(hpp, cpp, *ds);
ds->declaration(hpp);
ds->definition(cpp);
ds->declaration(this, hpp);
ds->definition(this, cpp);
}
std::string mainClass;
for (auto& cl : classes) {
toCompile.push_back(rootDir / cl->fileBaseName().concat(".cpp"));
std::ofstream hpp{rootDir / cl->fileBaseName().concat(".hpp")};
std::ofstream cpp{rootDir / cl->fileBaseName().concat(".cpp")};
genHeader(hpp, cpp, *cl);
cl->declaration(hpp);
cl->declaration(this, hpp);
if (cl->isMain) {
mainClass = cl->getName();
cpp << "namespace functors {\n";
Expand All @@ -292,9 +309,9 @@ std::string GenDb::emitMultipleFilesInDir(fs::path dir, std::vector<fs::path>& t
cpp << "}\n";
cpp << "} //namespace functors\n";
}
cl->definition(cpp);
cl->definition(this, cpp);
}
return mainClass;
}

} // namespace souffle::synthesiser
} // namespace souffle::synthesiser
26 changes: 17 additions & 9 deletions src/synthesiser/GenDb.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace fs = std::filesystem;

namespace souffle::synthesiser {

class GenDb;

class GenFile {
public:
GenFile(fs::path basename) : basename(std::move(basename)) {}
Expand Down Expand Up @@ -126,12 +128,12 @@ class Gen {
/* Emit the declaration of this construct in C++,
* typically what we would expect from a .hpp file
*/
virtual void declaration(std::ostream& o) const = 0;
virtual void declaration(const GenDb* db, std::ostream& o) const = 0;

/* Emit the Implementation of this construct in C++,
* typically what we would expect from a .cpp file
*/
virtual void definition(std::ostream& o) const = 0;
virtual void definition(const GenDb* db, std::ostream& o) const = 0;

std::string& getName() {
return name;
Expand Down Expand Up @@ -171,9 +173,9 @@ class GenFunction : public Gen {
override = true;
};

void declaration(std::ostream& o) const override;
void declaration(const GenDb* db, std::ostream& o) const override;

void definition(std::ostream& o) const override;
void definition(const GenDb* db, std::ostream& o) const override;

Visibility getVisibility() {
return visibility;
Expand Down Expand Up @@ -209,9 +211,9 @@ class GenClass : public Gen, public GenFile {
void addField(
std::string type, std::string name, Visibility, std::optional<std::string> init = std::nullopt);

void declaration(std::ostream& o) const override;
void declaration(const GenDb* db, std::ostream& o) const override;

void definition(std::ostream& o) const override;
void definition(const GenDb* db, std::ostream& o) const override;

void inherits(std::string parent) {
inheritance.push_back(parent);
Expand Down Expand Up @@ -252,8 +254,8 @@ class GenDatastructure : public Gen, public GenFile {
return definitionStream;
}

void declaration(std::ostream& o) const override;
void definition(std::ostream& o) const override;
void declaration(const GenDb* db, std::ostream& o) const override;
void definition(const GenDb* db, std::ostream& o) const override;

private:
std::optional<std::string> namespace_name;
Expand All @@ -268,6 +270,10 @@ class GenDatastructure : public Gen, public GenFile {
*/
class GenDb {
public:
void setNS(std::string ns);

std::string getNS(const bool spaced = true) const;

GenClass& getClass(std::string name, fs::path basename);
GenDatastructure& getDatastructure(
std::string name, fs::path basename, std::optional<std::string> namespace_opt);
Expand Down Expand Up @@ -299,6 +305,8 @@ class GenDb {
}

private:
// namespace of the generated code
std::string ns = "";
std::vector<Own<GenDatastructure>> datastructures;
std::vector<Own<GenClass>> classes;

Expand All @@ -311,4 +319,4 @@ class GenDb {
std::set<std::string> globalDefines;
};

} // namespace souffle::synthesiser
} // namespace souffle::synthesiser
26 changes: 18 additions & 8 deletions src/synthesiser/Synthesiser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2512,6 +2512,12 @@ void Synthesiser::generateCode(GenDb& db, const std::string& id, bool& withShare
db.addGlobalInclude("\"souffle/profile/ProfileEvent.h\"");
}

if (glb.config().has("generate-namespace")) {
db.setNS(glb.config().get("generate-namespace"));
} else {
db.setNS("souffle");
}

// produce external definitions for user-defined functors
std::map<std::string, std::tuple<TypeAttribute, std::vector<TypeAttribute>, bool>> functors;
visit(prog, [&](const UserDefinedOperator& op) {
Expand Down Expand Up @@ -3136,26 +3142,28 @@ void Synthesiser::generateCode(GenDb& db, const std::string& id, bool& withShare
factory.addDependency(mainClass, true);
factory.inherits("souffle::ProgramFactory");
GenFunction& newInstance = factory.addFunction("newInstance", Visibility::Public);
newInstance.setRetType("SouffleProgram*");
newInstance.body() << "return new " << classname << "();\n";
newInstance.setRetType("souffle::SouffleProgram*");
newInstance.body() << "return new " << db.getNS() << "::" << classname << "();\n";
GenFunction& factoryConstructor = factory.addConstructor(Visibility::Public);
factoryConstructor.setNextInitializer("ProgramFactory", "\"" + id + "\"");
factoryConstructor.setNextInitializer("souffle::ProgramFactory", "\"" + id + "\"");

std::ostream& hook = mainClass.hooks();
std::ostream& factory_hook = factory.hooks();

// hidden hooks
hook << "namespace souffle {\n";
hook << "SouffleProgram *newInstance_" << id << "(){return new " << classname << ";}\n";
hook << "SymbolTable *getST_" << id << "(SouffleProgram *p){return &reinterpret_cast<" << classname
<< "*>(p)->getSymbolTable();}\n";
hook << "SouffleProgram *newInstance_" << id << "(){return new " << db.getNS() << "::" << classname
<< ";}\n";
hook << "SymbolTable *getST_" << id << "(SouffleProgram *p){return &reinterpret_cast<" << db.getNS(false)
<< "::" << classname << "*>(p)->getSymbolTable();}\n";

hook << "} // namespace souffle\n";

factory_hook << "namespace souffle {\n";
factory_hook << "\n#ifdef __EMBEDDED_SOUFFLE__\n";
factory_hook << "extern \"C\" {\n";
factory_hook << "factory_" << classname << " __factory_" << classname << "_instance;\n";
factory_hook << db.getNS(false) << "::factory_" << classname << " __factory_" << classname
<< "_instance;\n";
factory_hook << "}\n";
factory_hook << "#endif\n";
factory_hook << "} // namespace souffle\n";
Expand Down Expand Up @@ -3183,7 +3191,9 @@ void Synthesiser::generateCode(GenDb& db, const std::string& id, bool& withShare

hook << "if (!opt.parse(argc,argv)) return 1;\n";

hook << "souffle::";
if (!db.getNS(false).empty()) {
hook << db.getNS(false) << "::";
}
if (glb.config().has("profile")) {
hook << classname + " obj(opt.getProfileName());\n";
} else {
Expand Down

0 comments on commit bfd3e9b

Please sign in to comment.